[Apache Tomcat 9] org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘messageSource’ defined in file 오류 해결방법
아파치 톰켓 서버 7 버전이 서비스 종료되어, 아파치 톰켓 9로 버전업하는 과정에 오류가 발생하였다.
@Controller, @Service, @Repository 어노테이션을 사용하는 클래스들은 스프링 구동시 Bean으로 등록을 하게 된다.
이를 위해 해당 어노테이션을 사용하는 클래스들을 스캔하게 되는데 <context:component-scan /> 태그를 활용하여 스캔할 프로젝트의 파일 위치를 지정할 수 있다.
[context-common.xml]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:/message/message-common</value>
<value>classpath:/egovframework/rte/fdl/idgnr/messages/idgnr</value>
<value>classpath:/egovframework/rte/fdl/property/messages/properties</value>
</list>
</property>
<property name="cacheSeconds">
<value>60</value>
</property>
</bean>
'''''''''''' 생략 '''''''''''''''''
<context:component-scan base-package="/">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>
태그 속성 중 base-package는 스캔을 시작할 패키지의 위치를 가리킨다. context-common.xml 파일을 열고 확인해보니 현재 ROOT(“/”) 로 되어 있다.
component-scan 용도는 무엇인가?
빈으로 등록할 클래스들을 스캔하여, 빈으로 등록해주는 것이다.
그 대상은 @Controller, @Service, @Component, @Repository 어노테이션을 붙인 클래스들이 대상이 된다.
component-scan은 기본적으로 @Component 어노테이션을 빈 등록 대상으로 포함한다.
[오류원인]
Tomcat8 이상 버전부터 tomcat 내부 클래스가 변경이 되면서 Spring 과 연관된 파일들에도 영향을 미치게 되었는데
그 중에 Component scan 시 base-package에는 패키지 이름을 식별 가능한 형태로 사용하도록 변경이 되어서 ROOT를 가리키는 / 를 사용할 수 가 없게 되었다.
[해결방법]
base-package 에 루트경로 '/' 가 아닌 프로젝트의 최상위 패키지명으로 변경해준다.
가령, 패키지명이 com.sample.project 라고 한다면, 최상위 패키지명은 com이 된다.
<context:component-scan base-package="com">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
context-common.xml 뿐만아니라 dispatcher-servlet.xml 파일 등에도 <context:component-scan /> 속성이 정의되어 있을 수 있으니 프로젝트에서 모든 파일에서 찾기를 통해 검색 후 모두 적용해주어야 한다.
[REFERENCE]
- 스프링 component-scan 개념 및 동작 과정 (velog.io)
- https://www.egovframe.go.kr/home/qainfo/qainfoRead.do?menuNo=69&qaId=QA_00000000000019128