
의존관계 주입에는 다양한 방법이 있다.
- 생성자 주입
- 수정자 주입 (setter)
- 필드 주입
- 일반 메서드 주입
이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법.
특징
- 생성자 호출 시점에 딱 한 번만 호출되는 것이 보장됨
- "불변, 필수" 의존관계에 사용
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법
특징
- "선택, 변경" 가능성이 있는 의존관계에 사용
- 자바빈 프로퍼티 규약과 수정자 메서드 방식을 사용하는 방법이다.
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
System.out.println("memberRepository = " + memberRepository);
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
System.out.println("discountPolicy = " + discountPolicy);
this.discountPolicy = discountPolicy;
}
}
이름 그대로 필드에 바로 주입하는 방법.
특징
- 코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트하기 힘들다는 단점이 있음.ㅍ
- DI 프레임워크가 없다면 아무것도 할 수 없음.
- 그냥 사용하지 말 것.
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
일반 메서드를 통해 주입 받을 수 있다.
특징
- 한번에 여러 필드를 주입 받을 수 있다.
- 일반적으로 잘 사용하지 않음.
@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;
}
}
주입할 스프링 빈이 없더라도 동작해야할 때가 있음.
하지만 @Autowired만 사용하면 'required' 옵션의 기본 값이 'ture'로 설정되어 있기 때문에 자동 주입 대상이 없으면 오류가 발생함.
자동 주입 대상을 옵션으로 처리하는 방법
- @Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨
- org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력됨
- Optional<> : 자동 주입할 대상이 없으면 Optional.empty 가 입력됨
생성자 주입을 선택할 것..!
- 생성자 주입을 선택하는 이유는 여러가지가 있지만, 프레임워크에 의존하지 않고, 순수한 자바 언어의 특징을 잘 살리는 방법임
- 기본으로 생성자 주입을 사용하고, 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여.
- 항상 생성자 주입을 선택하고 가끔 옵션이 필요하면 수정자 주입을 선택. 필드 주입은 사용하지 말 것.
@Autowired는 타입(Type)으로 조회한다.
DiscountPolicy 의 하위 타입인 RateDiscountPolicy와 FixDiscountPolicy가 둘다 스프링 빈으로 선언되어있다면?
-->NoUniqueBeanDefinitionException 오류 발생
해결 방법
- @Autowired 필드 명 매칭
- @Qualifier 사용
- @Primary 사용
*Qualifier와 Primary의 우선 순위는 더 상세하게 동작하는 Qualifier임.