나만보는페이지

[Spring] classpath: vs classpath*: 본문

spring

[Spring] classpath: vs classpath*:

pplenty 2020. 3. 16. 23:45

spring classpath: vs classpath*:

이슈

Invalid bound statement (not found)
웹 어플리케이션을 리팩토링하고, 모듈 별로 분리하는 작업을 하는 과정에서 mapperLocations 에 설정된 mapper xml 을 읽지 못하고 Exception 을 뱉었다.
보통 세션팩토리 빈을 아래와 같이 설정하고, 프로퍼티 값으로 xml 의 경로를 AntPattern 으로 설정해 해당 경로의 모든 xml 을 파일을 가져올 수 있도록 설정한다.

<bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>

원인 파악

리팩토링 과정에서 수정된 사항 중 의심이 가는 부분이 있었다. mapper xml 파일을 공용으로 사용하기 위해 별도의 모듈로 옮겼는데 그 부분이 문제가 될 것 같았다.
역시나 jar 로 말려 들어간 xml 파일들만 스캔되지 않고 있었다.
mybatis 에서 제공하는 SqlSessionFactoryBean 의 mapperLocations 값은 Resource[] type 이다.

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

  private static final Log logger = LogFactory.getLog(SqlSessionFactoryBean.class);

  private Resource configLocation;

  private Resource[] mapperLocations;

// ...
}

공식 문서

프로퍼티로 입력된 String type 의 경로 패턴은 PathMatchingResourcePatternResolver 에 의해 해석되어 주입된다.
스프링 javadoc api 를 살펴 보았다.
Spring doc

There is special support for retrieving multiple class path resources with the same name, via the "classpath*:" prefix.
For example, "classpath*:META-INF/beans.xml" will find all "beans.xml" files in the class path, be it in "classes" directories or in JAR files.

결론

classpath: 대신 classpath*: 를 사용해야만 jar 파일의 classpath 디렉토리까지 resolve 된다.
아래와 같이 path 를 수정하니 정상적으로 패턴에 만족하는 모든 xml 파일이 스캔되었다.

<bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="mapperLocations" value="classpath*:mapper/*.xml" />
</bean>

참고

https://docs.spring.io

Comments