스프링 강의(인프런)

스프링 Bean이 중복됐을 경우 해결 방법

indeep 2023. 6. 14. 22:56

조회 대상 빈이 2개 이상일 때 해결 방법은 총 3가지가 있다.

 

1. @Autowired 필드 명 매칭

2. @Qualifier 

3. @Primary

 

이 글에서는 2, 3번에 대한 방법을 소개한다.

 

@Qualifier

추가 구분자를 붙여주는 방식이다. 빈 이름을 변경하는 것이 아니다!!

우선 컴포넌트로 등록하는 클래스에 @Qualifier("지정할 이름") 으로 명시해준다.

@Component
@Qualifier("main")
public class FixDiscountPolicy implements DiscountPolicy{

    private int discountFixAmount = 1000; // 1000원 할인 고정

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

 

그리고 DiscountPolicy를 주입해주는 위치에 @Qualifier("해당 이름") 으로 명시해준다.

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository,@Qualifier("main") DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

 

위 코드에서 보면 OrderServiceImpl에서 생성자 주입을 하는데 DiscountPolicy 타입을 찾아서 주입하게 만들었다.

현재 코드에는 없지만 DiscountPolicy 타입을 가진 빈이 2개가 등록이 된 상태다.(RateDiscountPolicy, FixDiscountPolicy)

 

테스트를 실행하면 DiscountPolicy 타입을 가진 빈이 2개라서 에러가 나게 되는데 @Qualifier 어노테이션을 써서 main이라는 이름을 가진 빈을 꺼내오도록 만들었다.

 

그러면 에러가 발생하지 않고 main이라는 @Qualifier을 찾아서 주입을 시켜준다.

 

이것도 실행되는 순서가 있다.

1. @Qualifier

2. 빈 이름 매칭

3. NoSuchBeanDefinitionException 예외 발생

 

 

@Primary

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

주로 이 방법을 많이 사용한다고 한다(김영한 강사님 피셜)

 

// 할인 금액을 리턴한다.
@Component
@Primary
public class FixDiscountPolicy implements DiscountPolicy{

    private int discountFixAmount = 1000; // 1000원 할인 고정

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

이렇게 Primary 어노테이션을 달아주면 해당 어노테이션이 달린 빈을 우선 순위로 가지게 된다.

그래서 빈이 중복되면 우선 순위가 있는 빈을 찾아서 주입시켜주는 방식이다.

 

 

 

@Qualifier vs @Primary

만약에 이 두 개가 전부 사용됐다면 어떻게 우선 순위를 정할까?

 

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

 

 

반응형