조회한 빈이 2개 이상인 경우

Mina Park·2023년 10월 22일
  • @Autowired는 기본적으로 타입으로 조회
    • 하지만, 타입이 동일해서 선택된 빈이 2개 이상인 경우 문제 발생
@Component
public class FixDiscountPolicy implements DiscountPolicy {}

@Component
public class RateDiscountPolicy implements DiscountPolicy {}
  • 위와 같이 DiscountPolicy가 있고, 하위 타입인 FixDiscountPolicy, RateDiscountPolicy가 모두 의존관계 자동주입이 실행되면 -> NoUniqueBeanDefinitionException 오류 발생
@Autowired
private DiscountPolicy discountPolicy

어떻게 해결할 수 있을까?

  1. @Autowired 필드명 매칭
  • 타입 매칭 후 스프링빈이 여러개 있을 경우 자동으로 필드 이름, 파라미터 이름으로 추가 매칭을 시도함
@Autowired
private DiscountPolicy rateDiscountPolicy //이름 변경
  1. @Qualifier 사용
  • 추가 구분을 해주는 방식
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
@Qualifier("mainDiscountPolicy") DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
  1. Primary 사용
  • 우선순위를 정하는 방식
  • @Autowired 에서 여러 빈이 매칭되면 @Primary가 우선권을 갖게됨
@Component
@Primary 
public class RateDiscountPolicy implements DiscountPolicy {} //RateDiscountPolicy가 우선권

@Component
public class FixDiscountPolicy implements DiscountPolicy {}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}

@Qualifier의 경우, 문자열을 직접 기재하기 때문에 컴파일시 타입 체크가 안되는 문제가 있음 -> 어노테이션 직접 만들기를 통해 해결

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}
@Component
@MainDiscountPolicy  // 직접 정의한 어노테이션 적용
public class RateDiscountPolicy implements DiscountPolicy {}
@Autowired
public DiscountPolicy setDiscountPolicy(@MainDiscountPolicy DiscountPolicy
discountPolicy) {
this.discountPolicy = discountPolicy;
}

0개의 댓글