우리는 스프링을 사용할 때 스프링 컨테이너에 있는 Bean을 @Autowired로 자동 주입 해서 사용 할 수 있다.
@Autowired는 타입으로 조회한다.
하지만 조회시 선택된 빈이 2개 이상일 경우에는 문제가 발생한다.
해당 인터페이스를 구현한 두개의 구현채가 스프링에서 관리하는 Bean으로 등록되어있다.
그래서 해당 주입을 받은 생성자에서 DiscountPolicy를 주입받으면 두개의 2개 이상의 선택된 빈이 발생하게 된다(하위 타입).
single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy
이러한 문제를 해결해보자.
@Autowired 필드 명 매칭
@Autowired는 첫번째로 타입 매칭을 시도하고 이때 여러 빈이 조회되면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.
해당 사진과 같이 필드명 혹은 파라미터 명에 빈이름으로 매칭하게 되면 해당 문제를 해결할 수 있다.
@Qualifier
@Qualifier 이 어노테이션은 추가 구분자를 붙여주는 방법이다. 주입시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.
빈 등록시 @Qualifier 사용해 지정한 이름을 정해주고 주입시에는 @Qualifier를 붙여주고 등록한 이름을 적어준다.
@Qualifier도 첫번째로는 Qualifier 끼리 매칭하고 두번쨰로는 없으면 빈 이름으로 매칭한다. 그래도 조회가 조회된 빈이 없으면 NoSuchBeanDefinitionException 예외가 발생한다.
위 사진처럼 사용해도 문제가 없지만 @Qualifier("~~")는 문자열 이기때문에 개발자가 실수로 오타가 발생해도 컴파일 단계에서는 찾을 수가 없다. 그래서 해당 기능을 어노테이션으로 만들어서 사용하면 더 좋게 사용할 수 있다.
@Qualifier 에 있는 내용으로
해당 어노테이션을 생성후 그냥 @MainDiscountPolicy 를 가져다 쓰면 끝이다.
@Primary
@Primary 는 우선순위를 정하는 방법이다 @Autowired 시에 여러 빈이 매칭되면 @Primary가 우선권을 가진다.
우선순위
@Primary @Qualifier 를 사용하는 경우 @Qualifier의 우선순위가 더 높다. 스프링은 자동보다는 수동이, 넒은 범위보다는 선택권이 보다 좁은 범위를 높은 우선순위로 둔다.
참고자료