이전 포스팅까지는 클래스 타입으로 빈을 조회해서 자동으로 의존관계 주입하는 방식을 사용했다.
그런데 만약 의존관계 자동 주입 시 같은 클래스 빈이 두 개 이상이라면 스프링에서는 NoUniqueBeanDefinitionException 오류가 발생한다. 이렇게 빈이 여러 개일 때에는 어떻게 해야 할까?
해결하는 방법은 여러 가지가 있다.
- @Autowired 필드명 매칭
- @Qualifier 사용
- @Primary 사용
하나씩 알아보자
@Autowired 필드명 매칭
먼저 타입 매칭을 시도한 후에 빈이 여러 개라면 추가로 동작하는 기능이다. 필드명을 특정 구현 클래스 이름으로 설정해두면 해당 클래스 빈으로 매칭을 시도한다.
예를 들어 다음과 같은 필드를 선언한다면 DiscountPolicy가 여러 개일 때 rateDiscountPolicy로 매칭을 시도한다.
@Autowired
private DiscountPolicy rateDiscountPolicy
@Qualifier 사용
Qualifier는 그냥 추가 구분자를 붙여주어서 스프링이 빈을 구별하는데 도움을 주는 기능이다. 다음과 같이 사용할 수 있다.
@Component
@Qualifier("mainCity")
public class SuwonCity implements City {}
생성자 파라미터 부분에 @Qualifier를 사용해서 명시해줄 수 있다.
@Autowired
public CitySerivceImpl(CitizenRepository citizenRepository, @Qualifier("mainCity") City city) {
...
}
만약 @Qualifier를 통해서 빈을 찾지 못하면 해당 구분자와 같은 이름의 스프링 빈을 추가로 찾는다. 하지만 명확한 방법은 아니기 때문에 @Qualifier를 정확하게 사용하는 자세가 필요하다.
@Primary 사용
같은 타입의 스프링 빈이 여러 개가 있을 때 우선순위를 설정하는 방법이다. 다음과 같이 특정 빈이 더 높은 우선순위를 가지도록 할 수 있다.
@Component
@Primary
public class SuwonCity implements City {}
@Component
public class BusanCity implements City {}
위와 같이 설정하면 당연하게도 SuwonCity가 먼저 주입된다.
@Qualifier와 @Primary의 혼용 (김영한 님의 실무 꿀팁)
- 주로 의존 대상이 되는 스프링 빈은 @Primary를 적용하자. 다른 곳에서 의존 관계를 주입받을 때 편하게 주입받을 수 있다.
- 가끔 의존 대상이 되는 스프링 빈은 의존관계를 주입받는 쪽에서 @Qualifier를 사용해 명시적으로 주입받을 수 있도록 하자.
- 이렇게 하면 코드를 깔끔하게 유지할 수 있다.
+ 스프링은 자동보다는 수동이, 넓은 범위의 선택권보다는 좁은 범위의 선택권이 우선순위가 높다. 따라서 @Qualifier가 우선권이 높다.
같은 타입의 빈을 모두 주입받기 <Map, List>
현재 시스템에 여러 가지 할인 정책이 있다고 가정해보자. 할인 정책이 멤버의 어떤 속성 값을 보고 동적으로 정해져야 한다면 우리는 모든 할인 정책을 주입받을 필요성이 있다.
이때 Map 또는 List 형태로 필드를 설정하면 자동 의존관계 주입을 통해서 해당 타입의 스프링 빈들을 모두 주입받을 수 있다.
@Service
@RequiredArgsConstructor
public class DiscountService {
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policies;
...
}
reference
https://www.inflearn.com/course/스프링-핵심-원리-기본 편
'Spring' 카테고리의 다른 글
빈 스코프 (0) | 2022.04.29 |
---|---|
자동, 수동의 올바른 실무 운영 기준 (0) | 2022.04.08 |
nginx - 리버스 프록시로 스프링 CORS 문제 해결하기 (0) | 2022.04.07 |
생성자 주입과 스프링 (0) | 2022.04.06 |
스프링 컴포넌트 스캔 (0) | 2022.04.03 |