Spring

[Spring] @Autowired 빈 탐색 전략과 @Qualifier와 @Primary

HGLee-- 2022. 10. 13. 21:57

1. 빈(Bean) 등록과 조회 규칙


[ 빈(Bean) 등록 ]

Spring은 기본적으로 메소드/클래스의 이름을 Bean의 이름으로 사용한다.

@Bean
public DiscountPolicy fixDiscountPolicy() {
    return new FixDiscountPolicy();
}

@Bean
public DiscountPolicy rateDiscountPolicy() {
    return new RateDiscountPolicy();
}

 

하지만 개발자가 직접 빈의 이름을 부여할 수도 있다.

@Bean("fixDiscountPolicy")
public DiscountPolicy fixDiscountPolicy() {
    return new FixDiscountPolicy();
}

@Bean("rateDiscountPolicy")
public DiscountPolicy rateDiscountPolicy() {
    return new RateDiscountPolicy();
}

 

[ 빈(Bean) 조회 규칙(전략) ]

@Autowired가 등록된 빈을 찾을 때에는 다음과 같은 매칭 규칙으로 빈을 조회한다.

  1. 주입받고자 하는 타입으로 매칭을 시도한다.
  2. 타입이 여러 개면 필드 또는 파라미터 이름으로 매칭을 시도한다.

하지만 빈의 이름이 충돌되어 빈 이름만으로 해결이 불가능한 경우 또는 빈에 추가 구분자나 우선순위를 부여하고 싶은 경우에 @Qualifer나 @Primary 어노테이션을 이용해 편리하게 해결할 수 있다.

 

추가로 Spring은 @Resource라는 어노테이션도 제공하고 있다. @Resource는 @Autowired와 달리 필드 이름으로 빈을 찾는다.

  • @Autowired: 필드 타입을 기준으로 빈을 찾음
  • @Resource: 필드 이름을 기준으로 빈을 찾음

 

2. @Qualifier와 @Primary


[ @Qualifier - 빈의 Alias(구분자) ]

빈의 이름만으로 부족하고, 추가적인 정보가 필요할 수 있다. 그런 상황에서 Qualifier 어노테이션을 통해 빈에 추가 구분자(Alias)를 붙여줄 수 있다. (Bean의 이름을 바꾸는 것은 아니다.)

만약 우리가 위의 두 가지 DiscountPolicy 중에서 FixDiscountPolicy를 중점적으로 활용하고 싶다면, 해당 Bean에 mainDiscountPolicy라는 별칭 또는 구분자를 부여해줄 수 있다.

@Qualifier("mainDiscountPolicy")
@Bean
public DiscountPolicy fixDiscountPolicy() {
    return new FixDiscountPolicy();
}

 

그러면 다음과 같이 빈을 찾고자 하는 경우에 @Qualifer 어노테이션을 부여하여 빈을 찾도록 할 수 있다.

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

 

  1. 해당 @Qualifier가 붙은 빈을 조회한다.
  2. @Qualifier가 붙은 빈을 못찾으면 필드 또는 파라미터 이름으로 매칭을 시도한다.
  3. 그래도 찾지 못하면 NoSuchBeanDefinitionException 이 발생한다.

물론 빈을 찾고자하는 경우에 @Qualifier를 붙이지 않아도 정상적으로 작동한다. 하지만 이렇게 하면 유지보수 하면서 헷갈릴 수 있으므로 빈을 생성하는 곳과 찾는 곳 모두에 @Qualifier를 붙여주도록 하자.

 

[ @Primiary - 빈의 우선순위 부여 ]

여러 타입의 빈이 존재할 때, 특정 빈을 우선적으로 주입하도록 하고 싶다면 @Primary 어노테이션을 사용할 수 있다. Spring이 타입으로 빈을 찾다가 Primary가 붙어있는 빈을 발견하면, 바로 해당 빈을 주입시킨다. 즉, @Primary는 여러 개의 빈들 중에서 우선순위를 부여하는 방법이다.

@Primary
@Bean
public DiscountPolicy fixDiscountPolicy() {
    return new FixDiscountPolicy();
}

만약 Primary와 Qualifier 모두 등록이 되어있다면 이름을 직접 지정해주는 Qualifier가 우선순위를 갖는다.

 

 

[ 빈 등록 출동 발생 ]

하지만 위와 같이 설정해주지 않아 빈 등록 시에 충돌이 발생한다면 Spring에서는 다음과 같이 처리가 된다.

  • 자동 빈 vs 자동 빈: 빈 이름 중복 에러 발생
  • 수동 빈 vs 자동 빈: 과거에는 수동 빈이 자동 빈을 덮어버렸음 But, 최근에는 에러를 발생시키도록 변경됨

 

 

 

 

[출처]

https://mangkyu.tistory.com/148?category=761302

 

[Spring] @Autowired 빈 탐색 전략과 @Qualifier와 @Primary

1. 빈(Bean) 등록과 조회 규칙 [ 빈(Bean) 등록 ] Spring은 기본적으로 메소드/클래스의 이름을 Bean의 이름으로 사용한다. @Bean public DiscountPolicy fixDiscountPolicy() { return new FixDiscountPolicy();..

mangkyu.tistory.com