조회 대상 빈이 2개 이상일 때 해결 방법은 총 3가지가 있다.
1. @Autowired 필드 명 매칭
2. @Qualifier
3. @Primary
이 글에서는 2, 3번에 대한 방법을 소개한다.
@Qualifier
추가 구분자를 붙여주는 방식이다. 빈 이름을 변경하는 것이 아니다!!
우선 컴포넌트로 등록하는 클래스에 @Qualifier("지정할 이름") 으로 명시해준다.
@Component
@Qualifier("main")
public class FixDiscountPolicy implements DiscountPolicy{
private int discountFixAmount = 1000; // 1000원 할인 고정
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP){
return discountFixAmount;
}else{
return 0;
}
}
}
그리고 DiscountPolicy를 주입해주는 위치에 @Qualifier("해당 이름") 으로 명시해준다.
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository,@Qualifier("main") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
위 코드에서 보면 OrderServiceImpl에서 생성자 주입을 하는데 DiscountPolicy 타입을 찾아서 주입하게 만들었다.
현재 코드에는 없지만 DiscountPolicy 타입을 가진 빈이 2개가 등록이 된 상태다.(RateDiscountPolicy, FixDiscountPolicy)
테스트를 실행하면 DiscountPolicy 타입을 가진 빈이 2개라서 에러가 나게 되는데 @Qualifier 어노테이션을 써서 main이라는 이름을 가진 빈을 꺼내오도록 만들었다.
그러면 에러가 발생하지 않고 main이라는 @Qualifier을 찾아서 주입을 시켜준다.
이것도 실행되는 순서가 있다.
1. @Qualifier
2. 빈 이름 매칭
3. NoSuchBeanDefinitionException 예외 발생
@Primary
우선 순위를 정하는 방법이다. @Autowired 시에 여러 번 매칭되면 @Primary가 우선권을 가진다.
주로 이 방법을 많이 사용한다고 한다(김영한 강사님 피셜)
// 할인 금액을 리턴한다.
@Component
@Primary
public class FixDiscountPolicy implements DiscountPolicy{
private int discountFixAmount = 1000; // 1000원 할인 고정
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP){
return discountFixAmount;
}else{
return 0;
}
}
}
이렇게 Primary 어노테이션을 달아주면 해당 어노테이션이 달린 빈을 우선 순위로 가지게 된다.
그래서 빈이 중복되면 우선 순위가 있는 빈을 찾아서 주입시켜주는 방식이다.
@Qualifier vs @Primary
만약에 이 두 개가 전부 사용됐다면 어떻게 우선 순위를 정할까?
@Primaty는 기본값처럼 동작하고, @Qualifier는 매우 상세하게 동작한다. 스프링은 자동보다는 수동, 넓은 범위의 선택권 보다는 좁은 범위의 선택권이 우선 순위가 높다. 따라서 여기서도 @Qualifier가 우선순위가 높다!
'스프링 강의(인프런)' 카테고리의 다른 글
./gradlew clean build 에러 발생 (0) | 2023.07.06 |
---|---|
@Configuration 없이 @Bean을 등록하는 경우 (0) | 2023.06.19 |
JSP와 서블릿의 차이 (0) | 2023.06.17 |
서블릿(Servlet)의 개념과 흐름 (0) | 2023.06.17 |