728x90
반응형
@Qualifier("mainDiscountPolicy") 이렇게 문자르 ㄹ적으면 컴파일 시 타입 체크가 안된다. 다음과 같은 애노테이션을 만들어서 문제를 해결할 수 있다.
Qualifier에서
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
를 복사해서
package hello.core.annotation;
import java.lang.annotation.*;
public @interface MainDiscountPolicy {
}
public 위에 복사한다.
package hello.core.annotation;
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)
@Inherited
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}
그리고 @Qualifier("mainDiscountPolicy")를 같이 적어준다.
위의 어노테이션들을 붙여주면 스프링 컨테이너 안에서 추가한 어노테이션들의 기능이 동작한다.
이제 만든 위의 어노테이션을 사용하러 가보자.
RateDiscountPolicy.java
package hello.core.discount;
import hello.core.annotation.MainDiscountPolicy;
import hello.core.member.Grade;
import hello.core.member.Member;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
//@Primary
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy{
private int discountPercent = 10;
// 쉽고 빠른 테스트 코드 만들기
// 테스트 하기를 원하는 메서드에 마우스 포인트를 찍어놓고 Ctrl + Shift + T
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP) {
return price * discountPercent / 100;
} else {
return 0;
}
}
}
RateDiscountPolicy.java 에서 @MainDiscountPolicy 어노테이션을 추가해주고,
OrderServiceImpl.java
package hello.core.order;
import hello.core.annotation.MainDiscountPolicy;
import hello.core.discount.DiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
//@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
// final을 붙이면 생성자에서만 쓸 수 있는 것이 장점
// final이 붙으면 무조건 필수로 초기화 되어야하는 값이 된다.
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice); // SRD를 잘 지킨 형식
return new Order(memberId, itemName, itemPrice, discountPrice);
}
// 테스트 용도
public MemberRepository getMemberRepository() {
return memberRepository;
}
}
생성자의 파라미터에서 DiscountPolicy 부분 앞에 @MainDiscountPolicy를 붙여주고
test에서 Run > All Tests로 전체 테스트 실행 하면
전체 테스트가 통과하는 모습을 볼 수 있다.
애노테이션에는 상속이라는 개념이 없다. 이렇게 여러 애노테이션을 모아서 사용하는 기능은 스프링이 지원해주는 기능이다.
@Qualifier 뿐만 아니라 다른 애노테이션들도 함께 조합해서 사용할 수 있다.
단적으로 @Autowired도 재정의 할 수 있다. 물론 스프링이 제공하는 기능을 뚜렷한 목적 없이 무분별하게 재정의하는 것은 유지보수에 더 혼란만 가중할 수 있다.
728x90
반응형
'스프링 > 핵심 원리' 카테고리의 다른 글
[Spring] 자동, 수동의 올바른 실무 운영 기준 (0) | 2022.03.03 |
---|---|
[Spring] 조회한 빈이 모두 필요할 때, List, Map (0) | 2022.03.03 |
[Spring] @Autowired 필드 명, @Qualifier, @Primary (0) | 2022.02.25 |
[Spring] 조회 Bean이 2개 이상 발생하는 문제 (0) | 2022.02.22 |
[Spring] 롬복과 최신 트렌드 - 롬복(lombok) 설정 - RequiredArgsConstructor (0) | 2022.02.21 |
댓글