问题描述
我在类路径的根目录下有下一个applicationContext.xml
文件:
I have next applicationContext.xml
file on the root of classpath:
<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
也存在于类路径的根目录中,具有以下内容:
props/datasource.properties
also exists on the root of classpath with such content:
jdbc.url=myjdbcurl
jdbc.driverclass=myClass
jdbc.username=myUserName
jdbc.password=myPassword
我有一个春季托管测试,在该测试中,我通过下一个注释声明使用先前提到的applicationContext.xml:
I have a spring managed test where I declare to use previously mentioned applicationContext.xml via next annotations:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
当我调用测试方法时,我会从spring中得到下一个错误:
When I invoke test method i get next error from spring:
org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driverclass}'
据我了解,sping不能解析对jdbc.driverclass的引用.我做错了什么?
As I understand sping didn't resolve reference to jdbc.driverclass. What have I done wrong?
PS:我使用的是Spring 3.2.3 Release
PS: I'm using spring 3.2.3.RELEASE
**
**
也许问题可能出在MapperScannerConfigurer
中.它是一个BeanDefinitionRegistryPostProcessor
,正如Javadoc所说:
Perhaps the problem may be in MapperScannerConfigurer
. It is a BeanDefinitionRegistryPostProcessor
and as Javadoc says:
因此,尚未使用MapperScannerConfigurer
通过带有BeanFacoryPostProcessor
的sqlSessionFactory实例化数据源对象(负责<context:property-placeholder/>
).所以我的问题变成了如何从<context:property-placeholder/>
和BeanDefinitionRegistryPostProcessor
(MapperScannerConfigurer
)重新排序BeanFacoryPostProcessor
?
So MapperScannerConfigurer
instantiates datasource object via sqlSessionFactory with BeanFacoryPostProcessor
(which is responsible for <context:property-placeholder/>
) have not been utilized. So my question transforms to how to reorder BeanFacoryPostProcessor
from <context:property-placeholder/>
and BeanDefinitionRegistryPostProcessor
(MapperScannerConfigurer
)?
经过几个小时的调查,我找到了解决方案:
After a couple hours of investigation I found the solution:
正如我之前所说,MapperScannerConfigurer
是一个BeanDefinitionRegistryPostProcessor
,它在负责<context:property-placeholder/>
的BeanFactoryPostProcessor
之前触发.因此,在创建MapperScannerConfigurer的过程中,将无法解析对外部属性的引用.在这种情况下,我们必须将数据源的创建推迟到应用了BeanFactoryPostProcessor
之后的时间.我们可以通过几种方式做到这一点:
As I said earlier MapperScannerConfigurer
is a BeanDefinitionRegistryPostProcessor
which fires before BeanFactoryPostProcessor
which is responsible for <context:property-placeholder/>
. So, during the creation of MapperScannerConfigurer references to external properties will not be resolved. In this case we have to defer the creation of datasource to the time after BeanFactoryPostProcessor
have been applied. We can do that in several ways:
- 从
MapperScannerConfigurer
中删除p:sqlSessionFactory-ref="sqlSessionFactory"
.在这种情况下,不会在MapperScannerConfigurer
之前而是在负责<context:property-placeholder/>
的BeanFactoryPostProcessor
之后创建数据源对象.如果applicationContext中有多个sqlSessionFactory,那么可能会有些麻烦 - 在mybatis-spring模块高于1.0.2的版本中,可以设置
sqlSessionFactoryBeanName
而不是sqlSessionFactory
.它有助于解决BeanFactoryPostProcessor
的PropertyPlaceHolder问题.这是解决mybatis-spring doc
- remove
p:sqlSessionFactory-ref="sqlSessionFactory"
fromMapperScannerConfigurer
. In this case datasource object will not be created beforeMapperScannerConfigurer
, but afterBeanFactoryPostProcessor
which is responsible for<context:property-placeholder/>
. If you have more than one sqlSessionFactory in applicationContext, than can be some troubles - In versions of mybatis-spring module higher than 1.0.2 there is a possibility to set
sqlSessionFactoryBeanName
instead ofsqlSessionFactory
. It helps to resolve PropertyPlaceHolder issue withBeanFactoryPostProcessor
. It is a recommended way to solve this issue described in mybatis-spring doc
推荐答案
简短形式:加载BeanDefinitionRegistryPostProcessor的实现的正确方法是什么?
Short form: What is the proper way to load an implementation of: BeanDefinitionRegistryPostProcessor?
展开的表单:有没有一种方法可以在创建任何bean之前加载BeanDefinitionRegistryPostProcessor.如果您看一下javadoc:
Expanded form: Is there a way to load BeanDefinitionRegistryPostProcessor before any beans have been created. If you look at the javadoc:
因此,它是在创建bean定义时但在创建任何bean之前加载的.如果我们只是在应用程序xml中将其创建为常规bean,那么它就无法实现首先拥有该bean的目的.
So it's meant to be loaded when bean definitions have been created but before any beans have been created. If we just create it as a regular bean in the application xml then it defeats the purpose of having this bean in the first place.
这篇关于context:property-placeholder无法解析引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!