
현재 존재하는 할인 정책은 두개 이다.
- FixDiscountPolicy: 1000원 할인 정책
- RateDiscountPolicy: 10% 할인 정책
@Component
public class FixedDiscountPolicy implements DiscountPolicy {}
@Component
public class RateDiscountPolicy implements DiscountPolicy {}
@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;
}
@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
@Qualifier("mainDiscountPolicy")이렇게 문자를 적으면 컴파일시 타입 체크가 안된다.
다음과 같은 애노테이션을 만들어서 문제를 해결할 수 있다.
// MainDiscountPolicy 애노테이션 생성
package hello.core.annotataion;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {}
//생성자 자동 주입
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
//수정자 자동 주입
@Autowired
public DiscountPolicy setDiscountPolicy(@MainDiscountPolicy DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
@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는 매우 상세하게 동작한다.스프링은
자동보다는 수동이,넒은 범위의 선택권 보다는 좁은 범위의 선택권이 우선 순위가 높다.
따라서 여기서도@Qualifier가 우선권이 높다.