조회 빈이 2개 이상일 때

naeganugu·2022년 7월 26일
0

스프링 마스터🌱

목록 보기
14/19

우리가 @Autowired를 써서 주입할 때, type으로 빈을 찾게 된다. ac.getBean(DiscountPolicy.class) 와 유사하게 동작하는 것이다. 그렇다면 타입으로 조회했을 때 빈이 2개 이상이면 문제가 발생한다.

NoUniqueBeanDefinitionException 오류가 발생한다.

  • @Autowired 필드 명 매칭
  • @Qualifier
  • @Primary

크게 위처럼 세 가지 방법으로 문제를 해결할 수 있다.

0. 기본 상황

아래에 설명을 위해 예시 상황을 설명하자면 DiscountPolicy ➡️ FixDiscountPolicy, RateDiscountPolicy, DiscountPolicy를 상속받아서 할인 정책을 만든다. 그래서 DiscountPolicy 타입으로 조회를 하면 두가지 빈이 조회가 된다.

1. @Autowired 필드 명 매칭

@Autowired는 기본적으로 타입 매칭 ➡️ 빈이 여러개 나오면 필드 이름, 파라미터 이름으로 빈 이름 매칭 순으로 동작한다.
우선 타입으로 빈을 찾고 여러개가 나오면, 이름까지 체크해보는 것이다.

@Autowired
private DiscountPolicy rateDiscountPolicy

2. @Qualifier

빈 이름은 그대로 사용하면서, @Qualifier라는 구분자를 붙여주는 방식이다.

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

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

빈 등록할 때 @Qualifier를 붙여준다.

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

주입할 때는 @Qualifier("등록한 이름")을 적어준다. 이때도 "mainDiscountPolicy"를 못 찾으면 mainDiscountPolicy라는 이름을 가진 스프링 빈을 찾는다. 동작은 이렇게 하지만, 이를 일부러 의도해서 쓰지는 말 것.
@Qualifier끼리 매칭 ➡️ 못 찾으면 빈 이름으로 매칭 ➡️ 그래도 못 찾으면 예외 발생

@Component를 통한 컴포넌트 스캔 말고, 직접 @Bean으로 빈 등록할 때도 @Qualifier는 사용 가능하다.

3. @Primary

말 그대로 @Primary가 우선권을 가진다.

예를 들어, rate DiscountPolicy가 우선권을 가지게 하려면 다음과 같이 하면 된다.

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

4. @Primary와 @Qualifier의 활용

그럼 둘 중에 뭐를 써야할까? @Qualifier의 단점은 @Qualifier를 붙여줘야 한다는 점이다. 예를 들어 자주 사용하는 건 @Primary로 @Qualifier 지정 없이 편하게 사용하고, 가끔 쓰는 건 @Qualifier 지정을 통해서 명시적으로 사용할 수도 있다.

둘 중에 우선 순위는 @Qualifier가 우선권이 높다.
대부분의 경우 수동 > 자동, 좁은 범위 > 넓은 범위 로 우선순위가 높다.

profile
seungseung-zanggu

0개의 댓글