Spring/김영한 스프링 핵심원리 - 기본편
[섹션 7-1] 다양한 의존관계 주입 방법
보름달빵
2024. 2. 27. 23:12
의존관계 주입은 크게 4가지 방법이 있다.
- 생성자 주입
- 수정자 주입(setter 주입)
- 필드 주입
- 일반 메서드 주입
1. 생성자 주입
생성자 주입이란 생성자를 통해 의존관계를 주입받는 방법이다.
지금까지 이용한 방식이 생성자 주입 방식이다.
- 컴포넌트 스캔을 통해 빈을 등록할 때 @Autowired 어노테이션을 통해 스프링 컨테이너에서 의존 관계에 있는 객체를 자동으로 주입 시켜준다.
- 생성자 주입은 불변,필수 의존관계에 사용함
- 생성자 호출시 딱 1번만 호출되는것이 보장된다.
불변: 한번 호출해서 관계를 주입해주면 값이 바뀌지 않으므로 '불변'이다.
필수: private final .... 로 설정 -> 무조건 값이 있어야함 - 생성자가 하나일때는 @Autowired를 생략해도 된다.
하지만 생성자가 두개라면 어떤 생성자를 호출해서 의존관계를 주입해줘야하는지 모르기 때문에 @Autowired를 지정해줘야한다.
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired// 생성자가 1개 -> 생략가능
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
스프링 컨테이너의 사이클은 2단계이다. 처음에 빈을 등록하고, 이후에 @Autowired로 의존 관계를 주입해준다
그런데 생성자 주입이 특이한게 이 경우에는 빈을 등록할 때 생성자를 호출하는데 이때 의존관계를 주입해줘야 생성자가 실행되므로 빈을 등록하면서 의존관계 주입도 같이 일어난다.
즉, 생성자 주입을 이용한다면 스프링 라이프 사이클에서 빈을 등록할 때 의존관계 주입도 동시에 설정되는 것
2. 수정자 주입(setter주입)
setter 메서드를 사용하여 의존 관계를 주입 받는 방법
@Component
public class OrderServiceImpl implements OrderService{
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository (MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
- 선택, 변경가능성이 있는 의존관계에 사용
- @Autowired 를 보고 setter메서드를 통해 의존관계를 주입
- 따라서 생성자를 먼저 실행하고, setter메서드를 호출함
※ 참고 @Autowired 의 기본 동작은 주입할 대상이 없으면 오류가 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false) 로 지정하면 된다.
3. 필드 주입
필드에 의존관계를 곧바로 주입받는 방법
@Component
public class OrderServiceImpl implements OrderService{
@Autowired private MemberRepository memberRepository;
@Autowired private DiscountPolicy discountPolicy;
- 코드가 매우 간결하지만, 외부에서 변경이 불가능해서 테스트 작성이 어렵다
- 사용하지 말자!
※ 참고: 순수한 자바 테스트 코드에는 당연히 @Autowired가 동작하지 않는다. 컨테이너를 테스트에 통합한 경우에만 가능하다.
Q. 외부에서 변경이 불가능 하다?
@Bean
OrderService orderService(MemberRepository memberRepoisitory, DiscountPolicy discountPolicy) {
return new OrderServiceImpl(memberRepository, discountPolicy);
}
다음 코드와 같이 @Bean 에서 파라미터에 의존관계는 자동 주입된다.
하지만 필드 주입을 사용하는 경우 @Autowired로 스프링을 통해 의존관계를 주입 받는 방법 말고는 의존성을 주입 받을 방법이 없다. 만약 주입 받고 싶다면 각각의 setter를 만들어주면 되는데 이러면 setter 주입과 다를 것이 없다.
또한 테스트를 위해 memberRepository를 다른 것으로 바꾸고자 하더라도 바꿀 수가 없다.
- SpringBootTest에서 테스트를 하면됨 : 스프링부트테스트 클래스는 스프링 부트를 띄워서 테스트 하기 때문에
4. 일반 메서드 주입
- 의존 관계를 주입 받는 방식으로 메서드를 이용하는 것이다.
- 한번에 여러 필드를 주입 받을 수 있다.
- 잘 사용하지는 않는다
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}