我applicationContext.xml
在类路径的根目录上有下一个文件:
<context:annotation-config />
<context:property-placeholder location="classpath:props/datasource.properties" />
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"
p:username="${jdbc.username}"
p:password="${jdbc.password}"
p:url="${jdbc.url}"
p:driverClassName="${jdbc.driverclass}"
p:validationQuery="SELECT sysdate FROM dual" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="datasource"
p:mapperLocations="classpath:mappers/*-mapper.xml" />
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="datasource" />
<bean id="mappeScannerConfigurere" class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactory-ref="sqlSessionFactory"
p:basePackage="com.mypackage" />
props/datasource.properties
也存在于类路径的根目录中,内容如下:
jdbc.url=myjdbcurl
jdbc.driverclass=myClass
jdbc.username=myUserName
jdbc.password=myPassword
我有一个 spring 托管测试,我通过下一个注释声明使用前面提到的 applicationContext.xml:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
当我调用测试方法时,我从春天得到下一个错误:
org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driverclass}'
据我了解,sping 没有解析对 jdbc.driverclass 的引用。我做错了什么?
PS:我正在使用spring 3.2.3.RELEASE
**
编辑
**
也许问题可能出在MapperScannerConfigurer
. 正如BeanDefinitionRegistryPostProcessor
Javadoc 所说:
对标准 BeanFactoryPostProcessor SPI 的扩展,允许 在常规 BeanFactoryPostProcessor 检测开始之前注册更多的 bean 定义
所以MapperScannerConfigurer
通过 sqlSessionFactory 实例化数据源对象BeanFacoryPostProcessor
(它负责<context:property-placeholder/>
)没有被利用。所以我的问题转变为如何BeanFacoryPostProcessor
从<context:property-placeholder/>
和BeanDefinitionRegistryPostProcessor
(MapperScannerConfigurer
)重新排序?
解决
经过几个小时的调查,我找到了解决方案:
正如我前面所说的,MapperScannerConfigurer
是一个BeanDefinitionRegistryPostProcessor
哪个火灾之前BeanFactoryPostProcessor
哪个负责<context:property-placeholder/>
。因此,在创建 MapperScannerConfigurer 期间,对外部属性的引用将不会被解析。在这种情况下,我们必须将数据源的创建推迟到BeanFactoryPostProcessor
应用后的时间。我们可以通过以下几种方式做到这一点:
- 从.
p:sqlSessionFactory-ref="sqlSessionFactory"
_MapperScannerConfigurer
在这种情况下datasource对象不会在之前创建MapperScannerConfigurer
,而是在之后BeanFactoryPostProcessor
负责<context:property-placeholder/>
。如果 applicationContext 中有多个 sqlSessionFactory,那么可能会有些麻烦 - 在高于 1.0.2 的 mybatis-spring 模块版本中,可以设置
sqlSessionFactoryBeanName
而不是sqlSessionFactory
. 它有助于解决 PropertyPlaceHolder 问题BeanFactoryPostProcessor
。这是解决 mybatis-spring doc中描述的此问题的推荐方法