@Autowired는 타입으로 의존성을 주입해준다

타입으로 조회하면 선택된 빈이 두 개 이상 일때 문제가 발생한다.

@Component
 public class FixDiscountPolicy implements DiscountPolicy {}
 
 @Component
 public class RateDiscountPolicy implements DiscountPolicy {}
 @Autowired
 private DiscountPolicy discountPolicy

위와 같이 빈이 두개 이상이고 타입으로 조회하는 @Autowired가 의존성 주입하려고 시도하면

NoUniqueBeanDefinitionException 예외 발생.

그러면 @Autowired로 의존관계 주입해주는 클래스를 fixDiscountPolicy, rateDiscountPolicy 등 하위타입으로 지정해주면 되는 거 아닌가?! → 하위타입으로 지정해주는 것은 DIP가 유배되고 유연성 떨어짐! 그리고 이름만 다르고 완전히 똑같은 타입의 스프링 빈이 2개 있을 때 해결이 안된다!

빈을 수동등록 해도 되겠지만, 의존관계 자동 주입에서 해결하는 3가지 방법이 있음!

  1. @Autowired 필드 명 매칭

    1. @Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름 또는 파라미터 이름으로 빈 추가함.
    2. 즉 타입 매칭의 결과가 2개 일때 필드 명으로 빈 이름을 매칭한다.
    3. 아래 코드처럼 필드명을 빈 이름으로 바꿔주면 정상 주입된다.
    @Autowired
     private DiscountPolicy rateDiscountPolicy
    
  2. @Qualifier 사용 (qualify : 자격을 얻다. 예선 통과자)

    1. 추가 구분자를 붙혀주는 방법. 아래 컴포넌트 등록 코드에서 다른 곳에서 구분할 수 있는 이름 추가!
    2. 주입시에 @Qualifier를 붙여주고 등록한 이름을 적어준다.
    3. 아래 생성자 자동 주입 예시에서 @Qualifier에 맞는 이름의 빈을 찾아 주입한다.
    4. setter, 필드 주입에도 다 된다.
    5. 만약 @Qualifier(”mainDiscountPolicy”)를 못찾으면 mainDiscountPolicy 이름의 빈을 찾는다
    @Component
    @Qualifier("mainDiscountPolicy") 
     public class FixDiscountPolicy implements DiscountPolicy {}
    
    @Autowired
     public OrderServiceImpl(MemberRepository memberRepository,
                            @Qualifier("mainDiscountPolicy") DiscountPolicy 
    discountPolicy) {
     this.memberRepository = memberRepository;
     this.discountPolicy = discountPolicy;
     }