Backend/Spring

[스프링핵심원리 - 기본편]@Autowired, @Quilifier, @Primary

seung_soos 2023. 3. 25. 20:19

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

DiscountPolicy의 구현체인 RateDiscountPolicy, FixDiscountPolicy를 둘다 @Component로 Bean등록을 하였다.

실행시

@Test
void basicScan(){
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);

    MemberService memberService = ac.getBean(MemberService.class);
    Assertions.assertThat(memberService).isInstanceOf(MemberService.class);
}

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderServiceImpl' defined in file [C:\java\inflearn\core\out\production\classes\hello\core\order\OrderServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'hello.core.discount.DiscountPolicy' available: expected single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy

 - '빈이 2개 등록되어있다' 라는 에러 발생

@Autowired

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

DiscountPolicy rateDiscountPolicy 필드명 매칭시 에러가 발생하지않는다.

@Autowired매칭정리

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

@Quilifier 

@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy{
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy{
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}
  • @Quilifider는 추가 구분자를 붙여주는 방법이다. 주입시 추가적인 방법을 제공하는것이지 빈이름을 변경하는것은 아니다.
  • @Quilifider로 주입할때 @Quilifider("mainDiscountPolicy")를 못찾으면 어떻게 될까? 
  • 그러면 "mainDiscountPolicy"라는 이름의 스프링 빈을 추가로 찾는다.
  • @Quilifider는 @Quilifider를 찾는 용도로만 사용하는개 명확하고 좋다고한다! 

@Quilifider정리

  1. @Quilifider끼리매칭
  2. 빈 이름 매칭
  3. "NoSuchBeanDefinitionException" 예외발생

▶모든 구현체에 @Quilifider를 사용해야하여 코드가 지저분해진다.

@Primary사용

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

 

▶팀 프로젝트시 Bean에러가 지속 발생한적이있다. 그 당시에는 프로젝트 개발에만 급급하여 스프링내부 구조 및 의존관계와 같이 내부적인 구조를 몰랐었다. 그당시 에러메세지를 구글링한결과 @Primary라는 어노테이션을 사용하라고하여 에러를 해결한적이있었던 기억이난다....!

 

 

강의출처 : 스프링 핵심 원리 - 기본편 - 인프런 | 강의 (inflearn.com)