5) RateDiscountPolicy 를 의존관계로 주입하려는 클래스 OrderServiceImpl코드를 열어보자.
DiscountPolicy 에 @Qualifier 를 지정하되, 방금 만든 @MainDiscountPolicy를 쓰자.
6) 로그를 보면 정상적으로 스프링 빈이 등록되고 의존관계도 주입됬음을 확인할 수 있다.
Creating shared instance of singleton bean 'orderServiceImpl'
Autowiring by type from bean name 'orderServiceImpl' via constructor to bean named 'memoryMemberRepository'
Autowiring by type from bean name 'orderServiceImpl' via constructor to bean named 'rateDiscountPolicy'
OrderServiceImpl 싱글톤 빈이 생성됬고,
생성자를 통해 memoryMemberRepository와 rateDiscountPolicy 빈이 의존관계 주입이 됬다.
다음 강의에서는조회한 빈이 모두 필요할 때 List, Map 으로 처리하는 방법을 배운다.
1. 조회할 빈이 2개 이상일 때의 문제를 어떻게 처리해야 할지 배운다. 2. @Autowired 필드 명을 매칭, @Qualifier, @Primary 사용법을 배운다.
'의존관계 자동 주입' 목차
1. 다양한 의존관계 주입 방법
2. 옵션 처리
3. 생성자 주입을 선택해라!
4. 롬복과 최신 트랜드
5. 조회 빈이 2개 이상 - 문제 (이번 포스팅)
6. @Autowired 필드 명, @Qualifier, @Primary
7. 애노테이션 직접 만들기
8. 조회한 빈이 모두 필요할 때, List, Map
9. 자동, 수동의 올바른 실무 운영 기준
5. 조회할 빈이 2개 이상일 때의 문제 해결하기
@Autowired 는 타입으로 빈을 조회한다.
1) 만약 타입이 같은 빈이 2개가 조회되면 문제가 생길까?
인터페이스 DiscountPolicy의 구현체 2개가 있다. RateDiscountPolicy와 FixDiscountPolicy 는 타입이 같다.
RateDiscountPolicy 만 컴포넌트 스캔으로 스프링 빈 등록했었는데. FixDiscountPolicy도 스프링 빈 등록하려고 한다.
스프링 빈 등록을 위해 컴포넌트 스캔을 하자.
2) orderServiceImple 에서 의존성 예외 발생했는데, DiscountPolicy 싱글 빈이 매칭되기를 기대했는데, 2개가 발견됬기 때문이다.
beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'orderServiceImpl' Unsatisfied dependency
nested exception is NoUniqueBeanDefinitionException:
No qualifying bean of type 'DiscountPolicy' available:
expected single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy
@Autowired 로 의존관계를 주입하려고 DiscountPolicy 타입의 스프링 빈을 뒤져봤더니
1개 매칭을 기대했는데, 2개의 스프링 빈이 RateDiscountPolicy와 FixDiscountPolicy 발견되서 에러가 났다.
3) 하위 타입인 fixDiscountPolicy 나 rateDiscountPolicy 를 적어야 할까? 아니다. 하위타입에 의존하면 DIP를 위반한다.
다음 시간에 해결책을 배워보자.
6. @Autowired 필드 명, @Qualifier, @Primary
타입이 같은 빈이 여러개 조회되면, 3가지 방법으로 해결할 수 있다.
1) @Autowired 필드 명을 매칭한다
@Autowired 의 스프링 빈 조회 순서-> 1. 타입 매칭, 2. 필드 명 또는 파라미터 명을 매칭
@Autowired 는 가장 먼저 스프링 빈의 타입을 매칭해보고. 빈이 2개 이상 조회되면 필드 명을 확인해서 매칭되는 하나를 조회한다.
이전 코드
@Autowired 필드 명을 매칭시키도록 변경한 코드
2) @Qualifier 추가 구분자를 붙여주기
추가적인 방법을 제공하는 것이지 빈 이름을 변경하는건 아니다.
예를 들어, RateDiscountPolicy 에 @Qualifier("mainDiscountPolicy")를 지정하고,
FixDiscountPolicy 에는 @Qualifier("fixDiscountPolicy")를 지정한다.
생성자 주입을 할 때 @Qualifier를 써주면 된다.
만약 해당 @Qualifier를 못찾으면 스프링은 그 이름으로 등록된 빈을 찾아본다.
@Qualifier의 스프링 빈 조회 순서-> 1. @Qualifier 끼리 매칭, 2. 빈 이름 매칭
@Qualifier 는 @Qualifier 를 찾는 용도로만 사용하는게 명확하고 좋다. 헷갈리게 하는 요소를 만들지 말자.
3) @Primary 우선순위를 지정하기 [ 편하고 자주 사용한다 ]
rate 할인정책을 항상 먼저 적용하고 싶다면, RateDiscountPolicy에 @Primary 를 붙인다.
생성자에는 DiscountPolicy 타입 그대로 둔다.
[ 참고 ] @Primary 는 언제 사용할까?
예를 들어, 메인 DB connection 을 주로 사용하고, 백업용 DB connection 이 있는 상황에서,
메인 DB connection 에 @Primary 를 걸어두자고 팀내에서 룰을 지정할 수 있다.