@Qualifier과 @Primary

이원석·2022년 1월 26일

Spring

목록 보기
8/20
post-thumbnail
*인프런 김영한 강사님의 강좌를 참고하여 정리한 내용입니다.*

조회 빈이 2개 이상이라면..


@Component를 클래스에 붙여 스프링 컨테이너에 해당 클래스를 스프링 빈으로 등록할 수 있었다! 그리고 @Autowired를 사용하여 생성자, 필드, 일반 메서드등에 의존관계를 자동 주입할 수 있었다.

생성자에 @Autowired를 통해 해당 파라미터와 스프링 빈에 등록된 객체들중 맞는 타입을 매칭하여 의존관계 주입을 하였다.

그런데!

만약 같은 인터페이스를 상속한 다른 두 객체가 스프링 빈에 등록되어 같은 타입으로 매칭된 객체가 2개 이상일 경우에는 NoUniqueBeanDefinitionException 예외가 발생한다!

그렇다면 어떻게 의존관계 주입을 해야할까?




해결방법


3가지 해결방법이 있다.

1. @Autowired 필드명 매칭

@Autowired
// private final DiscountPolicy discountPolicy private final DiscountPolicy rateDiscountPolicy

필드명 discountPolicy를 빈 이름으로 변경하면, 먼저 타입 매칭을 시도한 후 그 결과에 여러 빈이 있을 때 해당 필드명을 통해 매칭하여 정상 주입한다.

정리

  1. 타입 매칭
  2. 타입 매칭의 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭


2. @Qualifier 매칭

@Qualifier는 추가 구분자를 붙여주는 방법이다. 주입시 추가적인 매칭 방법을 제공하는 것으로 빈 이름을 변경하는 것은 아니다.


[빈 등록시]

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

[자동 주입시]

@Autowired
public OrderServiceImpl(
    	@Qualifier("mainDiscountPolicy") MemberRepository memberRepository) {
...
}

정리

  1. @Qualifier끼리 매칭
  2. 빈 이름 매칭
  3. 매칭되지 않는다면 NoSuchBeanDefinitionException 예외 발생

@Qualifier → 같은 @Qualifier 끼리 매칭 → 빈 이름 매칭 → 없을경우 예외 발생



3. @Primary 사용

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


@Component
@Primary
public class RateDiscountPolicy implemnes DiscountPolicy {}

빈 등록시에 우선권을 등록하면 @Qualifier 없이도 매칭이 된다.




@Primary와 @Qualifier 활용


코드에서 자주 사용하는 메인DB의 커넥션을 휙득하는 스프링 빈이 있고 코드에서 특별한 기능으로 가끔 사용하는 서브DB의 커넥션을 휙득하는 스프링이 있는 경우에, 메인DB의 커넥션을 휙득하는 스프링 빈은 @Primary를 적용하여 우선조회를 하고, 서브DB의 커넥션 빈을 휙득할 때는 @Qualifier를 지정하여 명시적으로 휙득 하는 방식으로 활용 가능하다.

ex) 비율할인 정책인 RateDiscountPolicy와 고정된 금액만큼 할인하는 정책인 FixDiscounPolicy가 있을 때, RateDiscountPolicy를 @Primary로 등록하여 우선권을 주고 FixDiscountPolicy는 @Qualifier를 등록하여 상황에 맞게 정책을 변경할 수 있다.


우선순위

기본값 처럼 동작하는 @Primary, 매우 상세하게 동작하는 @Qualifier. 스프링은 자동보다 수동이, 넓은 범위의 선택권 보다는 좁은 범위의 선택권이 우선 순위가 높다.
따라서 우선순위는 @Primary < @Qualifier

0개의 댓글