Spring/Spring 핵심 원리

[Spring] 조회 대상 빈이 2개 이상인 경우 어떻게 해결할까? (@Qualifier, @Primary)

SeongHun._. 2022. 12. 26. 17:32

조회 대상 빈이 2개 이상일 때 앞서 배웠던 것 처럼 오류가 발생하게 된다.

이를 해결하는 방법을 하나씩 알아보자.

 

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

  • @Autowired 필드명 매칭
  • @Qualifier → @Qualifier끼리 매칭 → 빈 이름 매칭
  • @Primary 사용

 

@Autowired 필드명 매칭

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

 

기존코드

@Autowired
private DiscountPolicy discountPolicy

 

필드명을 빈 이름으로 변경

@Autowired
private DiscountPolicy rateDiscountPolicy

 

필드명이 rateDiscoutPolicy이므로 정상 주입된다.

필드명 매칭은 먼저 타입 매칭을 시도하고 그 결과에 여러 빈이 있을 때 추가적으로 동작하는 기능이다.

타입 매칭 → 타입 매칭이 2개 이상일 때 필드명, 파라미터명으로 빈 이름 매칭

 

 

@Qualifier 사용

@Qualifier는 추가 구분자를 붙여주는 방법이며, 주입 시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하지는 않는다.

 

빈 등록시 @Qualifier("mainDiscountPolicy")

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

 

생정자 자동 주입 예시

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

 

수정자 자동 주입 예시

@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
	this.discountPolicy = discountPolicy;
}

 

@Qualifier로 주입할 때 @Qualifier("mainDiscountPolicy")를 못 찾으면 어떻게 될까? 그러면 "mainDiscountPolicy"라는 이름의 스프링 빈을 추가로 찾는다. 하지만 @Qualifier는 @Qualifier 를 찾는 용도로만 사용하는게 명확하고 좋다.

 

수동 빈 등록시에도 @Qualifier를 사용할 수 있다.

@Bean
@Qualifier("mainDiscountPolicy")
public DiscountPolicy discountPolicy() {
	return new ...
}

 

 

@Primary 사용

@Primary는 우선 순위를 정하는 방법으로, @Autowired 시에 여러 빈이 매칭되면 @Primary가 우선권을 가지게 된다.

 

rateDiscountPolicy가 우선권을 가지도록 하자.

@Primary
@Component
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}
//생성자
@Autowired
public OrderServiceImpl(DiscountPolicy discountPolicy, ...) {
    this.discountPolicy = discountPolicy;
    ...
}

//수정자
@Autowired
public DiscountPolicy setDiscountPolicy(DiscountPolicy discountPolicy) {
    this.discountPolicy = discountPolicy;
}

 

코드를 실행해보면 @Primary를 가진 클래스가 주입된다.  @Qualifier는 주입 받는 모든 코드에 @Qualifierfmf 붙어야 하는 번거로움이 있다.  반면 @Primary는 등록되는 클래스에 붙여주기만 하면 된다.

만약 @Primary가 여러 개인 경우  NoSuchBeanDefinitionException 오류가 발생한다.

 

 

@Primary vs @Qualifier

@Primary와 @Qualifier를 적절히 사용하는 것이 가장 이상적이라고 볼 수 있다. @Primary는 하나의 구현체 만 사용하고 @Qualifier는 디테일하게 접근하고 사용할 수 있다. 서로 같이 쓰이는 경우 @Qualifier가 우선순위가 더 높다.

 

 

Reference

 

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

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com