개발/Spring

(스프링 기본) 22 - 조회된 빈이 2개 이상 문제 (@Qualifier, @Primary)

개발하는 인사담당자 2024. 10. 28. 14:57

■ 조회된 빈이 2개 이상 발견 되면 생기는 문제 (UnsatisfiedDependencyException)

@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;
    }

 

@Autowired 는 타입으로 조회한다.

즉, ac.getBean(DiscountPolicy.class) 와 유사하게 동작한다. 

 

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderServiceImpl' defined in file [C:\study\core\build\classes\java\main\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

 

그런데 선택된 빈이 2개 이상이면 오류가 발생한다. 

 

■ 조회된 빈 2개 이상일 때 해결 방법

1. @Autowired 필드명 매칭

2. @Qualifier -> @Qualifier 매칭 -> 빈 이름 매칭

3. @Primary 사용

 

1. @Autowired 필드명 매칭

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = rateDiscountPolicy;
}

 

타입 매칭 시도하고, 여러 빈이 있다면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.

다음과 같이 파라미터를 rateDiscountPolicy 로 바꿔주니 오류가 해결되었다. 

 

@Autowired
private DiscountPolicy rateDiscountPolicy;

 

필드명 파라미터를 변경해줘도 된다. 

 

* @Autowired 필드명 매칭 정리

1) 타입 매칭

2) 타입 매칭 결과 2개 이상일 경우,,= 필드명 또는 파라미터 명으로 빈 이름 매칭

 

2. @Qualifier 사용

@Qualifier 는 추가 구분자를 붙여주는 방법이다.

즉, 주입 시 추가적인 방법 제공이지 빈 이름 변경이 아니다. 

 

@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy{

 

주로 쓰는 빈을 @Qualifier 로 등록한다. 

 

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

 

그리고 의존성 주입 시 @Qualifier(mainDiscountPolicy) 를 넣어주면

해당 @Qualifier 로 등록된 의존성을 주입시켜 준다. 

 

* @Qualifier 매칭 정리

1)  @Qualifier  끼리 매칭

2) 빈 이름 매칭

3) NoSuchBeanDefinitionException 예외 발생

 

3. @Primary 사용

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy{

 

@Primary 는 우선순위를 정하는 것이다.

@Primary 가 우선권을 가진다. 

 

■ 활용

@Primary : 메인 데이터베이스 커넥션 획득하는 스프링 빈 

@Qualifier : 서브 데이터베이스 커넥션 빈을 획득할 때 

 

스프링은 자동보다 수동, 넓은 범위보다 선택권이 좁은 범위가 우선 순위가 높다.

즉 @Qualifier 가 우선순위가 더 높다. 

 

출처 : 김영한 스프링 핵심 원리 - 기본편

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B

 

스프링 핵심 원리 - 기본편 강의 | 김영한 - 인프런

김영한 | 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보

www.inflearn.com