의존관계 주입은 다양한 방법이 있다.
말 그대로 생성자를 통해 주입하는 것이다.
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
이렇게 생성자를 통해서 의존관계를 주입 받는다. 만약 생성자가 하나라면 @Autowired를 생략해도 자동으로 주입을 해준다.
@Autowired으로 의존관계 자동 주입도 스프링 빈에만 해당한다.
생성자 호출 시점에 딱 1번만 호출이 된다.
📌 불변, 필수 의존관계에 사용된다.
setter를 통해서 의존관계를 주입하는 방법이다.
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
setter 위에 @Autowired를 붙여서 의존관계를 주입해준다.
📌 선택, 변경 가능성이 있는 의존관계에 사용
@Autowired
private MemberRepository memberRepository;
코드는 상당히 간결해보이나, 의존관계 주입이 아니면 따로 할 수 있는 게 없다. 외부에서 변경이 불가능하다보니 테스트에도 유연하지 못하다.
그냥 쓰지 말자! 굳이 써야한다면 테스트 코드에서나 @Configuration 같은 설정 정보 같은 곳에서만 사용한다.
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
위 코드처럼 쓰는 것. 하지만 일반적으로 잘 쓰지 않는다. 굳이?
📌 의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 주입이 가능하다! 스프링 빈으로 등록되지 않는 클래스 안에서 @Autowired를 써도 동작하지 않는다. 위 예제들 모두 클래스 위에 @Component 어노테이션이 붙어 스프링 빈으로 등록이 되는 애들이라 @Autowired를 통한 DI도 가능한 것이다.
만약 주입할 스프링 빈이 없을 때는 어떻게 할까? @Autowired는 기본 required = true라 의존관계 주입 대상이 없다면 오류가 난다.
@Autowired(required=false)
어노테이션을 붙일 때, 옵션 값을 준다. 만약에 주입할 대상이 없다면, 메서드 자체가 호출이 되지 않는다.
@Autowired
public void setNoBean2(@Nullable Member member) {
System.out.println("setNoBean2 = " + member);
}
대상이 없으면 null이 입력된다.
@Autowired(required = false)
public void setNoBean3(Optional<Member> member) {
System.out.println("setNoBean3 = " + member);
}
주입할 대상이 없으면 Optional.empty가 입력된다.
4가지 경우나 봤지만 그냥 생성자 주입을 써라!
- 생성 시점에 주입되고 변경이 되지 않는다.
- 순수 자바만을 사용할 때 더 유리하다.
- 의존관계 주입이 누락되었을 경우에, 컴파일 오류가 발생한다.
- final 키워드를 쓸 수 있다.