NoUniqueBeanDefinitionException: No qualifying bean of type
'hello.core.discount.DiscountPolicy' available: expected single matching bean
but found 2: fixDiscountPolicy,rateDiscountPolicy
이렇게 DiscountPolicy의 하위 타입 2개를 모두 스프링 빈으로 선언하면 NoUniqueBeanDefinitionException 오류가 발생한다.
의존성 주입하는 부분에서 DiscountPolicy 대신 하위 타입으로 지정할 수도 있지만 이런 방법은 DIP를 위배하고 유연성이 떨어진다. 게다가 이름만 다르고 완전히 똑같은 타입의 스프링 빈이 2개 있는 상황이라면 해결되지 않는다.
@Qualifier를 붙여 구분해준다. 주입할 때 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.
publicclassOrderServiceImpl { @AutowiredpublicOrderServiceImpl(MemberRepository memberRepository,// 주입할 빈 지정 @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {this.memberRepository= memberRepository;this.discountPolicy= discountPolicy; }}
publicclassOrderServiceImpl { @AutowiredpublicDiscountPolicysetDiscountPolicy(// 주입할 빈 지정 @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy ) {return discountPolicy; }}
publicclassAppConfig {// 직접 빈을 등록하는 경우는 이렇게 사용할 수 있다. @Bean @Qualifier("mainDiscountPolicy")publicDiscountPolicydiscountPolicy() {returnnew... }}
@Qualifier로 주입할 때 @Qualifier("mainDiscountPolicy")를 못찾으면 mainDiscountPolicy라는 이름의 스프링 빈을 추가적으로 찾는다. 하지만 경험상 @Qualifier는 @Qualifier를 찾는 용도로만 사용하는 게 명확하고 좋다.
@Qualifier끼리 매칭
빈 이름 매칭
없으면 NoSuchBeanDefinitionException 발생
@Primary
우선 순위를 정하는 방법이다. @Autowired할 때 여러 빈이 매칭되면 @Primary 붙은 빈이 우선권을 가진다.