본문 바로가기

소프트웨어

Spring Bean 중복 에러

반응형

실무에서 중복 Bean 에러를 만난 적이 있었는데요~

관련된 내용을 정리해보겠습니다!

 

 

문제 재현

 

 

우선 문제 재현을 위해서 spring initializer 에서 위와 같이 설정하여 프로젝트를 생성했습니다

 

먼저 Interface 를 정의합니다

 

package com.example.dupbean.service;

public interface RecommendService {
    String getRecommendServiceName();
}

 

그리고 Interface 를 구현하는 두 가지 클래스의 Bean을 @Order 를 적용해서 만듭니다

package com.example.dupbean.service;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

@Order(1)
@Service
public class MockRecommendBO implements RecommendService {
    @Override
    public String getRecommendServiceName() {
        return "mock";
    }
}

 

package com.example.dupbean.service;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

@Order(2)
@Service
public class LocalRecommendBO implements RecommendService {
    @Override
    public String getRecommendServiceName() {
        return "local";
    }
}

 

Interface 를 기준으로 Bean 을 가져와서 사용하는 부분을 구현합니다

package com.example.dupbean.controller;

import com.example.dupbean.service.RecommendService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class RecommendController {
    private final RecommendService recommendService;

    @GetMapping("/recommend/name")
    public String getRecommendName() {
        return recommendService.getRecommendServiceName();
    }
}

 

실행해보면 아래와 같이 에러가 발생합니다

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-02-22T16:32:55.299+09:00 ERROR 51647 --- [dupbean] [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.dupbean.controller.RecommendController required a single bean, but 2 were found:
	- localRecommendBO: defined in file [/Users/user/temp/playground/dupbean/build/classes/java/main/com/example/dupbean/service/LocalRecommendBO.class]
	- mockRecommendBO: defined in file [/Users/user/temp/playground/dupbean/build/classes/java/main/com/example/dupbean/service/MockRecommendBO.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

 

bean 을 사용하는 부분에서는 single bean 을 사용하고 있는데, 실제로 bean 은 두 개가 있다는 내용의 에러입니다

 

@Order 어노테이션을 사용해서 bean 을 선택하려고 한 것이 문제죠!

 

결론

 

현업에서는 java.io.IOException: java.lang.reflect.InvocationTargetException 가 발생하는 경험을 했었는데요

회사에서 경험한 것을 자세히 공유하기는 어렵지만, 아마 원인은 비슷할 것이라고 생각합니다

 

애시당초 @Order 어노테이션은 같은 타입의 bean 들의 순서를 지정할 뿐 bean 을 선택하는 기준을 설정하는 것은 아닙니다

 

그러므로 위 에러 메시지의 Action: 하위 내용처럼 @Primary 나 @Qualifier 를 사용하는 것이 좋습니다

그런데 개인적으로는 아래와 같이 Bean의 우선순위를 구분할 때에는 Annotation 보다는 아래와 같이 모든 Bean을 가져온 다음에 Factory 패턴을 편이 더 좋을 것 같습니다 🤔

 

private final List<RecommendService> recommendServiceList;

 

물론 잠깐의 테스트를 위한 Bean 들이라면 @Primary 를 사용하거나 주석처리하는 것이 훨씬 편리할 것 같습니다 😁

반응형