【发布时间】:2013-07-07 13:30:51
【问题描述】:
我在类路径的根目录中有下一个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"})
当我调用测试方法时,我从 spring 收到下一个错误:
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 的扩展, 允许注册更多的 bean 定义 在常规 BeanFactoryPostProcessor 检测开始之前
所以MapperScannerConfigurer通过sqlSessionFactory实例化数据源对象BeanFacoryPostProcessor(负责<context:property-placeholder/>)没有被利用。
所以我的问题转变为如何从<context:property-placeholder/> 和BeanDefinitionRegistryPostProcessor(MapperScannerConfigurer) 重新排序BeanFacoryPostProcessor?
已解决
经过几个小时的调查,我找到了解决方案:
正如我之前所说的MapperScannerConfigurer 是一个BeanDefinitionRegistryPostProcessor,它在BeanFactoryPostProcessor 之前触发,它负责<context:property-placeholder/>。因此,在创建 MapperScannerConfigurer 期间,对外部属性的引用将不会被解析。在这种情况下,我们必须将数据源的创建推迟到应用 BeanFactoryPostProcessor 之后的时间。我们可以通过多种方式做到这一点:
- 从
MapperScannerConfigurer中删除p:sqlSessionFactory-ref="sqlSessionFactory"。在这种情况下,不会在MapperScannerConfigurer之前创建数据源对象,而是在负责<context:property-placeholder/>的BeanFactoryPostProcessor之后创建。如果 applicationContext 中有多个 sqlSessionFactory,那就麻烦了 - 在高于 1.0.2 的 mybatis-spring 模块版本中,可以设置
sqlSessionFactoryBeanName而不是sqlSessionFactory。它有助于解决BeanFactoryPostProcessor的 PropertyPlaceHolder 问题。这是解决mybatis-spring doc中描述的这个问题的推荐方法
【问题讨论】:
-
您的 Spring 上下文配置中是否还有其他
PropertyPlaceholderConfigurer? see this thread -
肯定不行,我是在setLoctions方法中设置断点检查的:只调用一次
-
我会尝试使用领先的
/作为属性位置:location="classpath:/props/datasource.properties" -
我有同样的问题,我只是删除了 autoWire=“byName”,属性文件就可以工作了。
-
@maks 你开膛手。我遇到了同样的问题,只要我添加了
MapperScannerConfigurer,它就会与我的属性占位符搞砸。查看代码时,我发现它实现了BeanDefinitionRegistryPostProcessor,这让我相信它是原因并最终找到了你的问题。回答你自己的问题,伙计!这是必要的确切解决方案:)