본문 바로가기
Spring(JAVA Framework)/Spring Core

@ Autowired 사용시 조회 빈이 중복되는 경우

by 걸어가는 신사 2021. 8. 19.

1. 조회 빈이 2개 이상인 경우

(1) 문제 발생

  • @Autowired는 타입(Type)으로 조회한다.
  • 타입으로 조회하기 때문에 ac.getBean(DiscountPolicy.class)와 유사하게 동작
  • 스프링 빈 조회에서 학습했듯이 타입으로 조회하면 선택된 빈이 2개 이상일 때 문제가 발생

 

DiscountPolicy의 하위 타입인 FixDiscountPolicy, RateDiscountPolicy 둘 다 스프링 빈으로 선언
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
@Component
public class RateDiscountPolicy implements DiscountPolicy {}
@Autowired
private DiscountPolicy discountPolicy
  • 이후 의존관계 자동 주입을 실행하면 NoUniqueBeanDefinitionException 발생한다.

 

(2) 해결 방법

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

 

(2-1) @Autowired 필드 명 매칭

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

 

@Autowired
private DiscountPolicy rateDiscountPolicy
  • 필드 명이 rateDiscountPolicy이므로 정상 주입된다.
  • 필드 명 매칭은 먼저 타입 매칭을 시도하고 그 결과에 여러 빈이 있을 때 추가로 동작하는 기능

 

(2-2) @Qualifier 사용

@Qualifier는 추가 구분자를 붙여주는 방법. 주입 시 추가적인 방법을 제공하는 것이다.
  • @Qualifier 사용 시 매칭 순서
    • @Qualifier끼리 매칭
    • 빈 이름 매칭
    • NoSuchBeanDefinitionException
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
  • 빈 등록 시 @Qulifier를 붙여 준다.
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
 @Qualifier("mainDiscountPolicy") DiscountPolicy 
discountPolicy) {
 this.memberRepository = memberRepository;
 this.discountPolicy = discountPolicy;
}
  • 생성자 주입 시 @Qulifier를 붙여준다.
  • @Qualifier로 주입할 때 @Qualifier("mainDiscountPolicy")를 못 찾으면 mainDiscountPolicy라는 이름의 스프링 빈을 추가로 찾는다. (하지만 이렇게 사용되는 것을 지양해야 한다.)

 

(2-3) @Primary 사용

@Primary는 우선순위를 정하는 방법이다. @Autowired 시에 여러 빈이 매칭 되면 @Primary가 우선권을 가진다.
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}
  • rateDiscountPolicy가 우선권을 가진다.
//생성자
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
 DiscountPolicy discountPolicy) {
 this.memberRepository = memberRepository;
 this.discountPolicy = discountPolicy;
}
  • 코드가 가장 깔끔해진다.

 

2. 정리

  • 코드에서 자주 사용하는 스프링 빈 : @Primary 사용
    • ex) 메인 데이터베이스의 커넥션을 획득하는 스프링 빈
  • 특별한 기능으로 가끔 사용하는 스프링 빈 : @Qualifier 사용
    • ex) 서브 데이터베이스 커넥션 빈을 획득하는 스프링 빈
  • 우선순위
    • 스프링은 자동보다는 수동, 넓은 범위의 선택권보다는 좁은 범위의 선택권이 우선순위가 높다.
    • @Qualifier의 우선권이 높다.

 

 


본 글은 김영한 님의 "스프링 핵심 원리"(인프런) 유료 강의를 들으며 요약, 정리하고 일부 정보를 추가 작성한 것입니다.

반응형

'Spring(JAVA Framework) > Spring Core' 카테고리의 다른 글

조회한 모든 빈이 가져오기 (List, Map)  (0) 2021.08.19
Lombok 라이브러리  (0) 2021.08.19
의존관계 자동 주입 방법  (0) 2021.08.19
컴포넌트 스캔 (Component Scan)  (0) 2021.08.18
Singleton (싱글톤)  (0) 2021.08.18

댓글