SpringBoot 기반의 프로젝트를 진행하던 중에 발생된 에러..
***************************
APPLICATION FAILED TO START
***************************
Description:
Field visitBaseInfoService in com.idrsoft.insight.web.client.visitor.baseinfo.VisitorBaseInfoController required a single bean, but 2 were found:
- visitBaseInfoServiceImpl: defined in file [C:\Dev\100. STS\sts-4.19.0\workspace-insighthub\.git\insight-hub\insight-web\target\classes\com\idrsoft\insight\web\client\visitor\baseinfo\impl\VisitorBaseInfoServiceImpl.class]
- visitorBaseInfoService: defined in file [C:\Dev\100. STS\sts-4.19.0\workspace-insighthub\.git\insight-hub\insight-web\target\classes\com\idrsoft\insight\web\client\visitor\baseinfo\VisitorBaseInfoService.class]
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
위 Controller 에서 @Autowired 로 가져온 VisitorBaseInfoService 라는 서비스가 2개 이상의 빈을 가지고 있어서 @Qualifier 이나 @Primary 어노테이션을 써서 사용하라는 의미의 오류를 발생하고 있는데요.
지금 사용하고 있었던 패키지의 구조는 다음과 같았습니다.
insight
ㄴ com.idrsoft.insight.web
ㄴ client
ㄴ visitor.baseInfo
ㄴ impl
ㄴ VisitorBaseInfoServiceImpl.java
ㄴ VisitorBaseInfoController.java
ㄴ VisitorBaseInfoMapper.java
ㄴ VisitorBaseInfoService.java
보통 스프링 패키지를 만들 때 위와 같은 형태로 만들곤 하는데요.
Mapper 에 대한 특정 SqlSession 을 사용하기 위해 아래와 같이 사용되어 집니다.
아래 그림과 같이 @Mapper 어노테이션을 붙이고,
CustomDataSourceConfiguration 에서 @MapperScan 의 basePackages 를 통해 @Mapper 들을 포함시키죠.
그러면, basePackages 에 등록된 Mapper 들을 아래의 Configuration 에 설정된 DataSource SqlSession을 사용하게 됩니다.
문제는..
위와 같은 패키지 구조일 경우에 문제가 발생하는데
@MapperScan 은 interface 로된 모든 것들을 Mapper 라고 판단하고 Bean 을 생성한다는 것 입니다.
아래에서 Bean 으로 만들어지면 안되는 Service Interface 가 Bean 으로 생성된다는 문제가 발생합니다.
insight
ㄴ com.idrsoft.insight.web
ㄴ client
ㄴ visitor.baseInfo
ㄴ impl
ㄴ VisitorBaseInfoServiceImpl.java
ㄴ VisitorBaseInfoController.java
ㄴ VisitorBaseInfoMapper.java -> @MapperScan 으로 정상적으로 Bean 등록
ㄴ VisitorBaseInfoService.java -> @MapperScan 으로 의도치 않은 Bean 등록
위와 같다면, Controller 에서 @Autowired 를 통해 SingleTon Bean 을 가져온다고 착각하고 사용하여맨 처음과 같은 오류가 발생되어 지는 것 입니다.
이미 VisitorBaseInfoService 를 구현하는 Impl 구현체에 @Service 어노테이션을 달아줬기 때문에
서비스 빈은
visitorBaseInfoService 라는 빈 1개
visitorBaseInfoServiceImpl 라는 빈 1개
총 두 개의 빈을 생성하기 때문에 Controller 에서 @Autowired 로 가져오면 당연히 오류가 발생되는 것 입니다.
물론 @Qualifier 이나 @Primary 를 통해 위 오류를 해결할 수 있겠지만
근본적인 해결 방법은 아니라고 생각됩니다.
결론!
해결법은 다음과 같습니다.
위와 같이 지정된 패키지의 모든 Interface 를 빈으로 만드는 것이 아니라
@MapperScan 에 있는 속성 중에 annotationClass 를 사용하여 @Mapper 어노테이션이 붙은 Interface 들 만을 빈으로 만들겠다 라는 설정을 하면 되겠습니다~~~
'Spring' 카테고리의 다른 글
Spring lombok 사용법 (0) | 2023.06.23 |
---|