조회 대상 Bean 이 2개 이상 일때 해결 방법 (+우선 순위)
현재 DiscountPolicy 인터페이스로부터 FixDiscountPolicy 와 RateDiscountPolicy 2개의 기능의 빈을 사용하고 있다면
컴파일 에러가 발생 한다.
@Component
public class FixDiscountPolicy implements DiscountPolicy{
@Component
public class RateDiscountPolicy implements DiscountPolicy{
@Component
public class OrderServiceImpl implements OrderService{
// 기본 기능(인터페이스를 참조하는) (실제 구현 기능의 객체 생성) 인터페이스에서 받은 것
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// 생성자를 직접 생성 (객체 추가시 추가로 해당 객체를 생성자에 작성 해야된다)
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
현재 DiscountPolicy 객체를 @Autowired 를 통해 스프링빈에 등록하려고 하지만 DiscountPolicy 는 Fix 와 Rate 두개의 기능을 가지고 있기 때문에 빈의 우선순위를 결정하지 못해 컴파일 에러가 발생 한다.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderServiceImpl' defined in file [C:\Users\rainb\OneDrive\바탕 화면\study\core\out\production\classes\hello\core\order\OrderServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1: No qualifying bean of type 'hello.core.discount.DiscountPolicy' available: expected single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy
(요약 하자면 DiscountPolicy 라는 객체에 스프링 빈 parameter 는 1개만 담을수 있지만 현재 2개가 있다는 뜻)
해결 방안
1. @Autowired 필드명을 매칭
- 필드명을 변경하여 @Autowired 시킨다.
(필드명 매칭 후 코드)
@Component
public class OrderServiceImpl implements OrderService{
// 기본 기능(인터페이스를 참조하는) (실제 구현 기능의 객체 생성) 인터페이스에서 받은 것
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// 생성자를 직접 생성 (객체 추가시 추가로 해당 객체를 생성자에 작성 해야된다)
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = rateDiscountPolicy;
}
(DiscountPolicy → rateDiscountPolicy 로 변경)
- @Autowired 타입 매칭을 시도하고, 이 때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.
- 필드명이 rateDiscountPolicy 이므로 정상 주입 된다.
2. @Qualifier 사용
- RateDiscountPolicy 를 @Qualifier 사용하여 "mainDiscountPolicy" 라는 이름으로 지정 한다.
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy{
- 다음으로 RateDiscountPolicy 객체가 생성된 생성자 앞에 @Qualifier("mainDiscountPolicy")를 찾도록 지정해 준다.
@Component
public class OrderServiceImpl implements OrderService{
// 기본 기능(인터페이스를 참조하는) (실제 구현 기능의 객체 생성) 인터페이스에서 받은 것
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// 생성자를 직접 생성 (객체 추가시 추가로 해당 객체를 생성자에 작성 해야된다)
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
※ Qualifier 정리 (검색 순서)
step 1. @Qualifier 끼리 매칭
step 2. 빈 이름 매칭
step 3. 위 두가지 이름으로 매칭시에도 없을 시 NoSuchBeanDefinitionException 예외 발생
3. @Primary 사용 (우선순위 지정 방법)
@Primary 선언 시 최상위 우선 순위를 가진다.
@Component
@Primary
public class FixDiscountPolicy implements DiscountPolicy{
(*가장 보편적으로 사용)