: MemberController가 memberService와 memberRepository를 사용할 수 있도록 의존관계를 설정한다.
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
//Spring Container에 MemberController 객체를 넣고 Spring이 관리
// => Spring Bean이 관리된다고 말함
@Controller
public class MemberController {
private final MemberService memberService;
//MemberService 객체를 하나 생성하고 여러 Controller에서 공용으로 쓰게 하기
//Spring Container한테 등록하고 사용하면 됨 => 생성자로 연결
//필요한 의존 객체의 타입에 해당하는 Bean을 Spring Container에서 찾아서 자동으로 주입
@Autowired //Controller와 Service 연결
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
: 이때 MemberSercive class와 MemoryMemberRepository class에서도 애노테이션 설정 필요
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service // Client의 요청에 대한 비즈니스 로직을 수행. @Component의 하위 애노테이션
public class MemberService {
private final MemberRepository memberRepository;
//DI(Dependency Injection) 의존성 주입
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
//(...생략...)
}
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository // @Component의 하위 애노테이션
public class MemoryMemberRepository implements MemberRepository{
//(...생략...)
}
❗ 추가 설명
@Component:Bean객체를 만드는 역할. 개발자가 직접 컨트롤 할 수 있는 class에서 사용한다.@Component의 구체화된 형태로@Repository,@Service,@Controller가 있다.
- Bean이란? Spring Container에 등록되어 관리되는 객체
- Spring Container에 Spring Bean을 등록할 때 기본적으로 싱글톤으로 등록한다.
(유일하게 하나만 등록해서 공유)
=> 특별한 경우를 제외하고, 같은 Spring Bean이면 모두 같은 인스턴스.
- 생성자에
@Autowired가 있으면 스프링이 Spring Container에서 연관된 객체를 찾아서 넣어준다(주입).
- 객체 의존관계를 외부에서 넣어주는 것을 DI(Dependency Injection), 의존성 주입이라고 한다.
- Spring Container = Spring Bean Container = Spring Bean 혼용

memberController는 memberService가 필요하고 memberService는 memberRepository가 필요함 => 의존 관계(Autowired) 설정memberService 객체를 생성할때 @Service를 확인하고 Spring Container에 등록하면서 생성자를 호출함@Autowired를 확인하고 memberRepository가 필요하다는 것을 체크, Spring Container에 있는 memberRepository를 주입memberRepository의 구현체는 memoryMemberRepository므로 이걸 memberService에 주입해줌✍ 정리
- 컴포넌트 스캔 : 스프링 구동 시
@component관련 애노테이션이 있으면 모두 자동으로 Spring Container에 객체로 등록(=Spring Bean으로 등록)- 자동 의존관계 설정 :
@AutoWired는 연관 관계(선)을 이어주는 역할
❓ 컴포넌트 스캔 범위
: 실행 Application이 속한 package를 포함한 하위 패키지의 class에서만 가능.
package hello.hellospring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class HelloSpringApplication { public static void main(String[] args) { SpringApplication.run(HelloSpringApplication.class, args); } }위 코드의 경우 hello.hellospring 패키지 바깥의 class에서는
@component가 있어도 컴포넌트 스캔 안 함.
: MemberService와 MemeberRepository의 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행한다.
: MemberSercive class와 MemoryMemberRepository class에서 애노테이션 삭제
@Controller는 그대로 두기package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean //Spring Bean을 수동으로 입력
public MemberService memberService() { //Spring Container에 등록
return new MemberService(memberRepository()); //생성자에서 MemberRepository를 넣어줘야함
}
@Bean
public MemberRepository memberRepository() { //Spring Container에 등록
return new MemoryMemberRepository(); //구현체
}
}
memberService와 memberRepository를 둘다 Spring Container에 등록memberRepository를 memberService에 주입: 생성자를 통해 의존 관계 주입. 불변성 보장.
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired //생성자에 @Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
: 필드에 @Autowired 입력. 간단하지만 외부에서 접근 불가능 => 테스트하기 힘듦
@Controller
public class MemberController {
@Autowired private MemberService memberService; //필드에 @Autowired
}
: Setter를 통해 의존 관계 주입. 주입받는 객체가 변경될 가능성이 있는 경우 사용 (실제로는 극히 드묾)
@Controller
public class MemberController {
private MemberService memberService;
@Autowired //Setter를 생성하여 @Autowired 입력
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
💡💡💡 생성자 주입 방식을 권장
❗ 참고사항
- 실무에서 주로 정형화 된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용. 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경 해야하면 설정을 통해 스프링 빈으로 등록.
@Autowired를 통한 DI는helloController,memberService등과 같이 Spring Container에 올라간 객체에서만 동작. 스프링 빈으로 등록하지 않고 직접 생성한 객체(new)에서는 동작하지 않는다.