애너테이션 - Qualifier, Primary, 애너테이션 생성

인프런 스프링 핵심 원리 - 기본편 수강 중

조회할 빈이 2개 이상일 떄

  • @Autowired는 타입으로 조회하기 때문에 다음 코드와 유사한 동작을 한다
ac.getBean(DiscountPolicy.class)
  • 아래처럼 해당 타입의 빈이 여러개라면 문제 발생
    @Component
    public class FixDiscountPolicy implements DiscountPolicy {}
    
    @Component
    public class RateDiscountPolicy implements DiscountPolicy {}
    
  • 하위 타입으로 지정할 수도 있지만 이는 DIP 위배이며 유연성이 떨어짐

@Autowired 필드명 매칭

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

또는

@Autowired
private DiscountPolicy rateDiscountPolicy
  • @Autowired는 타입 매칭을 시도했을 때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 추가 매칭
  • 필드명을 빈 이름으로 변경해서 해결 가능
  • 필드명 rateDiscountPolicy으로 정상 주입

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;
}
  • 만약 못찾으면 mainDiscountPolicy 스프링 빈을 추가로 찾음
  • 그래도 없으면 NoSuchBeanDefinitionException 예외 발생
  • 모든 코드에 @Qualifier를 붙여주어야 하기 때문에 번거로움

@Primary

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy{}
  • @Primary는 우선순위를 정해주어 빈이 여러 개라면 @Primary를 가진 빈애 우선권을 가져간다
  • @Primary보다는 @Qualifier가 우선권이 높다
  • 스프링은 자동보다는 수동, 넓은 범위 보다는 좁은 범위의 선택권이 우선 순위가 높다

애너테이션 직접 생성

중복 빈을 조회할 때 구분자를 지정했던 @Qualifier 방식을 새로 직접 생성

정의

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {}

빈 등록

@Component
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy {}

생성자 또는 수정자

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}
  • 애너테이션에는 상속 개념이 없음
  • 여러 애너테이션을 모아서 사용하는 기능은 스프링이 제공
  • 다른 애너테이션들 조합해서 사용 가능

[참조] 인프런 스프링 핵심 원리 - 기본편 - 링크

끝!