코드 그라데이션

조회 빈이 2개 이상 - 해결 본문

Spring/핵심 원리 구현

조회 빈이 2개 이상 - 해결

완벽한 장면 2024. 2. 7. 12:49

해결 방법은 크게 3가지.

1. @Autowired 필드명 매칭

2. @Qualifier => @Qualifier끼리 매칭 => 빈 이름 매칭

3. @Primary 사용

 

 

@Autowired 필드명 매칭

이 생성자를 바꿔준다. 구체적 이름으로

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) { // 여기 변경
	this.memberRepository = memberRepository;
	this.discountPolicy = rateDiscountPolicy; // 여기 변경
}

 

전체 코드 OrderServiceImpl  

package inflearn.spring_core.order;

import inflearn.spring_core.discount.DiscountPolicy;
import inflearn.spring_core.member.Member;
import inflearn.spring_core.member.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) { // 여기 변경
        this.memberRepository = memberRepository;
        this.discountPolicy = rateDiscountPolicy; // 여기 변경
    }

    //테스트 용도 추가
    public MemberRepository getMemberRepository() {
        return memberRepository;
    }


    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

이렇게 하고 전 포스팅에서 실패했던 basicScan() 테스트를 다시 돌려보면

성공이 나온다.

 

물론 전체테스트 돌리면, xmlAppContext() 메서드는 실패가 나온다.

xml 등록할 때 discountPolicy 이름으로 등록해놨기 때문.

 

물론 그냥 필드명을 

@Autowired
private DiscountPolicy rateDiscountPolicy;

이렇게 수정해줘도 된다. (파라미터 인젝션 말고)

 

 

필드명 매칭은 먼저 타입 매칭을 시도 하고 그 결과에 여러 빈이 있을 때 추가로 동작하는 기능이다.

 

@Autowired 매칭 정리

 


@Qualifier 사용

@Qualifier 는 추가 구분자를 붙여주는 방법이다. 

주입 시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.

 

 

빈 등록시 @Qualifier를 붙여 준다.

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

주입시에 @Qualifier를 붙여주고 등록한 이름을 적어준다.

 

생성자 자동 주입 예시

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

 

수정자 자동 주입 예시

@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy")DiscountPolicy discountPolicy) {
	this.discountPolicy = discountPolicy;
}

 

다음과 같이 직접 빈 등록시에도 @Qualifier를 동일하게 사용할 수 있다.

 


@Qualifier 정리

 


 

@Primary 사용

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

 

rateDiscountPolicy 가 우선권을 가지도록 하자.

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {
}

@Component
public class FixDiscountPolicy implements DiscountPolicy {
}

 

사용코드

//생성자
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
	this.memberRepository = memberRepository;
	this.discountPolicy = discountPolicy;
}

//수정자
@Autowired
public DiscountPolicy setDiscountPolicy(DiscountPolicy discountPolicy) {
	this.discountPolicy = discountPolicy;
}

 

여기까지 보면 @Primary 와 @Qualifier 중에 어떤 것을 사용하면 좋을지 고민이 될 것이다.

@Qualifier 의 단점은 주입 받을 때 다음과 같이 모든 코드에 @Qualifier 를 붙여주어야 한다는 점이다.

 

 

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
	this.memberRepository = memberRepository;
	this.discountPolicy = discountPolicy;
}
  • 반면에 @Primary 를 사용하면 이렇게 @Qualifier 를 붙일 필요가 없다.

 

@Primary, @Qualifier 활용

 

 

우선순위

 

728x90

'Spring > 핵심 원리 구현' 카테고리의 다른 글

조회한 빈이 모두 필요할 때  (0) 2024.02.08
애노테이션 직접 만들기  (0) 2024.02.07
조회 빈이 2개 이상 - 문제  (0) 2024.02.06
Lombok과 최신 트렌드  (0) 2024.02.06
생성자 주입을 선택하라  (1) 2024.02.05
Comments