ABAP DUMP ERROR 24시

조회 @Bean이 2개 이상일 때 NoUniqueBeanDefinitionException 본문

[WEB]Back-end/Spring

조회 @Bean이 2개 이상일 때 NoUniqueBeanDefinitionException

이운형 2022. 1. 28. 22:09
반응형

# 인프런 김영한의 스프링 핵심 원리 - 기본편을 개인적으로 정리한 글입니다.

 

정리


 

Q. 조회 대상 bean이 2개 이상일때 어떻게 해결해?

1. @Autowired를 통해 생성자의 파라미터를 매칭시킨다

 

2. @Qualifier 를 통해 Bean 이름을 매칭한다.  // 실무에서는 Qualifier끼리 매칭시켜서 다루자! ==NoSuchBeanDefinitionException 조심하자.

 

3. @Primary를 통해 Bean을 매칭한다. // 조회 대상 Bean중 우선권을 갖게 한다.

 

 

Q . @Autowired를 통해 생성자의 파라미터를 매칭 어떻게 해?

@Autowired//ac.getBean(DiscountPolicy.class 와 유사한 기능)
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

로 변경해서 직접 사용한다.

@Autowired//ac.getBean(DiscountPolicy.class 와 유사한 기능)
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = rateDiscountPolicy;
}

Q .@Qualifier 를 통해 Bean 이름을 매칭 어떻게 해?

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

처럼 @Qualifier를 적어서 수동으로 등록한후 사용한다. 

Q .@Primary를 통해 Bean을 매칭 어떻게해?

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {

 사용하면 된다. // 우선권을 지닌 class에 @Primary를 넣어두면 된다. 

 

Q .@Primary vs @Qualifier

Qualifier 가 우선으로 작동한다.

 

살펴보기


Q .오류 상황

public class AutoAppConfigTest {

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

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

        OrderServiceImpl bean = ac.getBean(OrderServiceImpl.class);
        MemberRepository memberRepository = bean.getMemberRepository();

        System.out.println("memberRepository = " + memberRepository);

    }
}

다음과 같이 AutoAppConfig를 통해 Bean의 의존 관계를 주입한 상태이다.

이상태로 Test를 돌려보면

NoUniqueBeanDefinitionException : No qualifying bean of tpe.... DiscountPolicy =>  fixDiscountPolicy, rateDiscountPolicy에 관한 expected single matching bean but found2 에러가 발생

 

1.OrderServiceImpl의 생성자를 잘 보자!

@Component
//@RequiredArgsConstructor // final 붙은 녀석  생성자 만들어줌
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;


    @Autowired//ac.getBean(DiscountPolicy.class 와 유사한 기능)
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
@Component
public class FixDiscountPolicy implements DiscountPolicy {

    private int discountFixAmount = 1000;

    @Override
    public int discount(Member member, int price) {
        if (member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        } else {
            return 0;
        }
    }
}
@Component
public class RateDiscountPolicy implements DiscountPolicy {

    private int discountPercent = 10;

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP){
            return price * discountPercent /100;
        }else{
            return 0;
        }
    }
}

2. OrderServiceImpl은 생성자 파라미터로 DiscountPolicy를 갖는다.

@Autowired//ac.getBean(DiscountPolicy.class 와 유사한 기능)
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

 3. Component는 FixDiscountPolicy와 RateDiscountPolicy를 갖는다.

== 어떤 Bean을 가져와서 사용할지 모르는것!

 

반응형
Comments