이전 포스팅에서는 스프링 빈 등록 방법에 자동,수동으로 등록하는 방법이 있다고 정리 했었다. 스프링 컨테이너가 자동으로 스프링 빈 객체의 요구 사항에 맞는 다른 빈을 찾아 연결해주는 것을 오토와이어링(Autowiring) 이라고 하며, 2가지 방식이 있다.
- 타입을 사용한 방식
- 이름을 사용한 방식
필드 이름을 사용한 방식은 @Resource 애너테이션을 활용하는데 생성자 주입에는 사용하지 못한다. 이번 포스팅에서는 타입을 사용한 방식으로 지금까지 자주 봐왔던 @Autowired 애너테이션에 대해서 정리하고자 한다.
@Autowired
위에서 설명했듯이 @Autowired 애너테이션은 스프링 빈을 자동으로 등록 하는 방법 중 타입을 사용한 방식이며 다음과 같이 빈을 조회하고 매칭시키는 규칙이 있다.
- 주입받고자 하는 타입으로 매칭
- 매칭 타입이 복수일 경우, 필드 명이나 파라미터 명으로 빈 이름을 추가 매칭
아래와 같이 DiscountPolicy의 하위 타입인 FixDiscountPolicy , RateDiscountPolicy 가 있다고 하자.
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
@Component
public class RateDiscountPolicy implements DiscountPolicy {}
그리고 의존관계 주입 시, 아래와 같이 한다고 해보자.
@Autowired
private DiscountPolicy discountPolicy //편의상 필드 주입
이렇게 실행하면 컴파일 에러가 발생한다. ( NoUniqueBeanDefinitionException )
NoUniqueBeanDefinitionException: No qualifying bean of type
'hello.core.discount.DiscountPolicy' available: expected single matching bean
but found 2: fixDiscountPolicy,rateDiscountPolicy
하지만 아래와 같이 필드명을 빈 이름으로 바꿔서 시도한다면 정상적으로 가능하다.
@Autowired
private DiscountPolicy rateDiscountPolicy //빈 이름인 rateDiscountPolicy로 적어주었다.
이와같이 @Autowired는 먼저 타입 매칭을 시도하고, 중복의 경우 필드 명 혹은 파라미터 명으로 추가 매칭한다.
이 외에 @Qualifier , @Primary 애너테이션을 활용해 타입 중복을 해결하는 방법도 있는데 알아보자.
@Qualifier
@Qualifier는 추가 구분자 (alias)를 붙여주는 방법이다. 주의할 점은 빈의 이름을 변경하는 점이 아니라는 것.
아래와 같이 정률할인정책을 메인으로 사용하겠다고 별칭을 달아줄 수 있다.
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
주입 시에는 아래와 같이 @Qualifier를 붙여주고 등록한 이름을 적어준다.
@Autowired
public DiscountServiceImpl(@Qualifier("mainDiscountPolicy") discountPolicy) {
this.discountPolicy = discountPolicy;
}
아래와 같은 순서로 주입이 이루어 진다.
- @Qualifier가 붙은 빈을 조회
- @Qualifier가 붙은 빈을 찾지 못했으면, 필드명 또는 파라미터명으로 시도
- 실패했으면 NoSuchBeanDefinitionException 에러 발생
설명에서 알 수 있듯이 @Qualifier를 붙이지 않아도 가능하지만, 개발은 언제나 명확히 알 수 있는 것이 중요하기 때문에 해당 방법을 사용해 빈을 생성하거나 찾는 곳에는 모두 @Qualifier 애너테이션을 작성하자.
@Primary
@Primary 애너테이션은 우선적으로 매칭될 빈을 지정해 주는 방법이다.
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}
주입 시에는 @Autowired와 같은 방법이기 때문에 생략 ( @Qualifier와 같이 애너테이션을 붙일 필요가 없다.)
여기서 주의할 점은, @Qualifier는 별칭을 직접 지정하기 때문에 @Primary보다 우선권이 있어, @Primary기능을 사용하려면 @Qualifier 애너테이션이 없어야 한다.
마지막으로 생각해 볼 것은 @Autowired가 있기 때문에 @Qualifier와 @Primary를 활용할 곳이 있냐는 점이다.
메인DB와 커넥션을 획득하는 스프링 빈과 특별한 기능으로만 사용하는 서브DB와 커넥션을 획득하는 스프링 빈이 있다고 가정해보자. 이 경우에 메인DB와 커넥션을 획득하는 스프링 빈에는 @Primary 애너테이션을 적용해 쉽게 연결 해 조회하고, 서브DB와는 @Qualifier를 지정해 명시적으로 한다면 개발자 입장에서 알아보기 쉽고 유지보수에 유리 할 것이다.
'Backend > Spring' 카테고리의 다른 글
빈 스코프(Bean Scope)와 스코프가 다른 빈 주입 (0) | 2023.12.27 |
---|---|
빈 생명 주기(Bean Life Cycle)와 콜백(callback) (0) | 2023.12.24 |
다양한 의존관계 주입 방법 (생성자 주입을 선택해야 하는 이유) (0) | 2023.12.18 |
스프링 빈 설정하는 방법 (XML, @Configuration, @Component) (1) | 2023.12.17 |
스프링의 싱글톤 (+ 싱글톤 레지스트리란?) (0) | 2023.12.11 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!