일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- aop
- 디자인패턴
- Filter
- OOP
- aspect
- http
- request
- 스프링 시큐리티
- Interceptor
- 스프링
- SQL
- response
- Spring Security
- 스프링부트
- 인터셉터
- git
- 관점지향프로그래밍
- MYSQL
- exception
- network
- Spring
- java
- 객체지향프로그래밍
- Redis
- mybatis
- 자바
- proxy pattern
- spring boot
- 트랜잭션
- RestControllerAdvice
- Today
- Total
장쫄깃 기술블로그
[Spring Boot] 의존성 주입 시 Bean이 여러개라면? (@Primary, @Qualifier) 본문
[Spring Boot] 의존성 주입 시 Bean이 여러개라면? (@Primary, @Qualifier)
장쫄깃 2022. 6. 26. 00:52
들어가며
@Autowired는 Component Scan + @Component로 스프링 빈에 등록된 객체를 찾아서 필요한 의존관계를 설정한다. (우선적으로, 타입(Type)으로 해당 빈(Bean)을 찾는다.)
만약 @Autowired를 통한 자동 의존관계 주입 시 여러개의 빈이 존재한다면 어떻게 될까? 어떤 빈을 의존주입을 해야할 지 판단하지 못하는 경우 UnsatisfiedDependencyException 이 발생한다. UnsatisfiedDependencyException은 예외명에서도 알 수 있듯이 스프링 빈 객체들이 생성되는 과정에서 의존주입을 하게 되는데, 필드에 해당하는 의존관계를 만족시킬 수 없을 때 발생하는 예외이다.
그 중에서 대표적으로 NoUniqueBeanDefinitionException 가 있다.
@public class UserWebServiceImple {
@Autowired private UserService userService;
}
위와 같은 경우 UserService 타입의 구현체가 여러 개 존재하고 스프링 컨테이너에 빈으로 등록되어 있는 경우 스프링 컨테이너는 어떤 UserService를 의존주입해야 할 지 판단하지 못하기 때문에 NoUniqueBeanDefinitionException (유일하지 않은 빈 정의 예외)가 발생한다.
이러한 상황을 해결할 수 있는 3가지 방법에 대해서 설명해보려고 한다.
1. @Autowired 필드명 매칭
@Autowired는 우선적으로 타입(Type)으로 빈을 찾지만, 찾지 못하면 필드 이름으로 찾는 특징이 있다. 때문에, 내가 의존성 주입을 받는 필드 이름을 구현체의 이름으로 명시하여 찾게하는 방법이 있다.
@Autowired UserRepository userRepository;
@Autowired BoardRepository boardRepository;
@Autowired UserRepository vipUserRepository;
@Autowired BoardRepository noticeBoardRepository;
필드의 이름을 인터페이스가 아닌 실제 원하는 구현체의 이름으로 적용하는 방법이다. (vipUserRepository, noticeBoardRepository 등) 이렇게 필드명을 원하는 구현체와 일치시키면 여러개의 빈을 찾을 때 해결이 가능하다.
하지만 추천하는 방법은 아니다!
@Primary
@Primary 는 어노테이션을 붙혀서 우선순위를 지정할 때 사용한다. 특정 빈을 우선적으로 주입하고 싶은 경우 해당 어노테이션을 붙여준다.
@Component
@Primary
public class noticeBoardRepository implements boardRepository {
// ...
}
@Component
public class galleryBoardRepository implements boardRepository {
// ...
}
@Autowired boardRepository boardRepository; // noticeBoardRepository 빈 의존성이 주입됨!
@Primary 어노테이션을 붙혀 @Autowired 시 우선적으로 빈을 찾게 하면, 여러개의 빈을 찾을 때 원하는대로 해결이 가능하다.
실무에서 많이 사용하는 방법이다!
@Qualifier
@Qualifier(빈의 구분자) 는 빈에 구분자를 같이 삽입하여 사용할 의존 객체를 선택할 수 있도록 해준다.
@Qualifier("noticeBoardReposiroty")
@Component
public class noticeBoardRepository implements boardRepository {
// ...
}
@Qualifier("noticeBoardRepository")
@Autowired
BoardRepository boardRepository
해당 @Qualifier가 붙은 빈을 조회한다. 만약 빈을 찾지 못하면 필드 또는 파라미터 이름으로 매칭을 시도한다. 그래도 찾지 못하면 NoSuchBeanDefinitionException 가 발생한다.
@Qualifier를 붙이지 안아도 빈을 찾을 수는 있지만, 유지보수 시 혼란이 생길 수 있으므로 되도록이면 붙여주는 것이 좋다.
정리하며
@Primary와 @Qualifier를 적절히 사용하는 것이 가장 이상적이다.
- @Primary는 하나의 구현체만을 사용하게 하는 것
- @Qualifier는 @Primary보다 귀찮지만, 디테일하게 접하고 사용할 수 있음
- @Qualifier가 @Primary보다 우선순위가 높다!
(의도적으로 여러개의 빈을 가져와서 동적으로 처리하는 경우 위에 설명한 것 + Map/List 를 사용하면 좋음)
'Spring Framework > Spring Boot' 카테고리의 다른 글
[Spring Boot] Meta Annotation (@Target, @Retention) (0) | 2022.06.26 |
---|---|
[Spring Boot] 등록되는 빈의 순서를 정하자 (@DependsOn) (0) | 2022.06.26 |
[Spring Boot] request, response 한 번만 읽어올 수 있는 제약 해결 (0) | 2022.04.19 |
[Spring Boot] AOP 용어 (2) | 2022.04.15 |
[Spring Boot] AOP(Aspect Oriented Programming) 란? (0) | 2022.04.15 |