중복타입 Bean 등록 및 우선순위 지정 문제

선종우·2023년 7월 26일
0

1. 배경

  • 진행하던 프로젝트에서 Spring디버깅하면서 본 아이디어를 적용해보고자 하였다. 특정 인터페이스의 구현체들을 List에 담고 list를 순회하며 구현체의 응답값이 있을 경우 바로 return하는 구조이다.
@Service
@RequiredArgsConstructor
public class ExternalAddressApiServiceImpl implements ExternalAddressApiService{

    private final List<ExternalAddressApi> externalAddressApi;
    @Override
    public AddressApiResponse searchAddress(String query, String analyzeType, Integer page, Integer size) {
        for (ExternalAddressApi addressApi : externalAddressApi) {
            AddressApiResponse result = addressApi.searchAddress(query, page, size);
            if (result != null && !CollectionUtils.isEmpty(result.getContents())) {
                return result;
            }
        }
        return null;
    }

    @Override
    public AddressApiResponse searchAddress(String query) {
        return searchAddress(query, null, null, null);
    }
}

  • 여기서 ExternalAddressApi 구현체는 KakaoAddressApi와 NaverAddressApi이다. 각 구현체는 RestTemplate bean을 주입받는다.
    @Bean
    public RestTemplate kakaoRestTemplate(RestTemplateBuilder restTemplateBuilder) {
        생략
    }
    
    @Bean
    public RestTemplate naverRestTemplate(RestTemplateBuilder restTemplateBuilder) {
        생략
    }

2. 문제1 : Bean 중복에 의한 의존성 주입 결정

  • 처음에는 KakaoApi와 NaverApi 모두 RestTemplate bean을 아래와 같은 코드로 주입받았다.
private final RestTemplate restTemplate;
  • 결과는 아래와 같이 bean이 여러개라는 에러가 발생했다.
Parameter 0 of constructor in com.sun.external.api.KakaoAddressApi required a single bean, but 2 were found:
	- kakaoRestTemplate: defined by method 'kakaoRestTemplate' in class path resource [com/sun/external/config/RestTemplateConfig.class]
	- naverRestTemplate: defined by method 'naverRestTemplate' in class path resource [com/sun/external/config/RestTemplateConfig.class]
  • 그래서 우선 @Qualifier를 적용하여 문제를 해결하였다.
KakaoAddressApi.java
    @Qualifier("kakaoRestTemplate")
    private final RestTemplate restTemplate;
-----------------------------------------------    
NaverAddressApi.java
    @Qualifier("naverRestTemplate")
    private final RestTemplate restTemplate;
  • 찾다보니 중복빈이 있을 때 필드명과 같은 빈을 찾는다고 해서 아래 방법도 사용해보았다.
KakaoAddressApi.java
    private final RestTemplate kakaoRestTemplate;
-----------------------------------------------    
NaverAddressApi.java
    private final RestTemplate naverRestTemplate;

3. 문제2 : List에 빈 추가 시 우선순위 문제

  • ExternalAddressApiServiceImpl에서 List에 bean을 자동으로 주입받게 되는데, 이때 순서를 내가 정할 수 없다는 문제가 있었다. 특정 상황에서 특정 API가 먼저 호출되게 하고 싶다면? Bean 등록 우선순위가 애플리케이션 시작 때마다 달라진다면?
  • 이 문제 역시 @Order 애노테이션을 이용해 해결할 수 있었다.
@Order(1)
public class KakaoAddressApi implements ExternalAddressApi {

NaverAddressApi.java
@Order(2)
public class NaverAddressApi implements ExternalAddressApi{
KakaoAddressApi.java
  • 애노테이션을 이용해 순서를 지정해주었더니 내가 원하는 호출 순서가 보장되었다.

0개의 댓글