빈(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가 등록된 빈을 찾을 때에는 다음과 같은 매칭 규칙으로 빈을 조회한다.
- 주입받고자 하는 타입으로 매칭을 시도한다.
- 타입이 여러 개면 필드 또는 파라미터 이름으로 매칭을 시도한다.
하지만 빈의 이름이 충돌되어 빈 이름만으로 해결이 불가능한 경우 또는 빈에 추가 구분자나 우선순위를 부여하고 싶은 경우에 @Qualifer나 @Primary 어노테이션을 이용해 편리하게 해결할 수 있다.
Spring은 자바 표준 어노테이션인 @Resource라는 어노테이션도 기능을 지원하고 있다. @Resource는 @Autowired와 달리 필드 이름으로 빈을 찾는다.
- @Autowired: 필드 타입을 기준으로 빈을 찾음
- @Resource: 필드 이름을 기준으로 빈을 찾음
@Qualifier - 빈의 구분자
빈의 이름만으로 부족하고, 추가적인 정보가 필요할 수 있다. 그런 상황에서 Qualifier 어노테이션을 통해 빈에 추가 구분자를 붙여줄 수 있다. (Bean의 이름을 바꾸는 것은 아니다.)
만약 우리가 위의 두 가지 DiscountPolicy 중에서 FixDiscountPolicy를 중점적으로 활용하고 싶다면, 해당 Bean에 mainDiscountPolicy라는 별칭 또는 구분자를 부여해 줄 수 있다.
@Qualifier("mainDiscountPolicy")
@Bean
public DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
그러면 다음과 같이 빈을 찾고자 하는 경우에 @Qualifer 어노테이션을 부여하여 빈을 찾도록 할 수 있다.
public DiscountService(@Qualifier("mainDiscountPolicy") fixDiscountPolicy) {
this.discountPolicy = fixDiscountPolicy;
}
- 해당 @Qualifier가 붙은 빈을 조회한다.
- @Qualifier가 붙은 빈을 못 찾으면 필드 또는 파라미터 이름으로 매칭을 시도한다.
- 그래도 찾지 못하면 NoSuchBeanDefinitionException 이 발생한다.
물론 빈을 찾고자 하는 경우에 @Qualifier를 붙이지 않아도 정상적으로 작동한다. 하지만 이렇게 하면 유지보수 하면서 헷갈릴 수 있으므로 빈을 생성하는 곳과 찾는 곳 모두에 @Qualifier를 붙여주도록 하자.
@Primiary - 빈의 우선순위 부여
여러 타입의 빈이 존재할 때, 특정 빈을 우선적으로 주입하도록 하고 싶다면 @Primary 어노테이션을 사용할 수 있다. Spring이 타입으로 빈을 찾다가 Primary가 붙어있는 빈을 발견하면, 바로 해당 빈을 주입시킨다. 즉, @Primary는 여러 개의 빈들 중에서 우선순위를 부여하는 방법이다.
@Primary
@Bean
public DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
만약 Primary와 Qualifier 모두 등록이 되어있다면 이름을 직접 지정해 주는 Qualifier가 우선순위를 갖는다.
빈 등록 출동 발생
하지만 위와 같이 설정해주지 않아 빈 등록 시에 충돌이 발생한다면 Spring에서는 다음과 같이 처리가 된다.
- 자동 빈 vs 자동 빈: 빈 이름 중복 에러 발생
- 수동 빈 vs 자동 빈: 과거에는 수동빈이 자동 빈을 덮어버렸음, 최근에는 에러를 발생시키도록 변경됨
'Spring' 카테고리의 다른 글
필터(Filter) vs 인터셉터(Interceptor) 차이 (2) | 2023.05.12 |
---|---|
의존성 주입(Dependency Injection) (3) | 2023.05.11 |
@Configuration안에서 @Bean을 사용해야하는 이유 (0) | 2023.05.05 |
@Bean,@Configuration,@Component 차이점 (0) | 2023.05.05 |
@RequestBody, @ModelAttribute, @RequestParam의 차이 (0) | 2023.05.04 |