我在classpath的根目录下有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/>
)尚未被利用。
所以我的问题转变为如何从BeanFacoryPostProcessor
和<context:property-placeholder/>
(BeanDefinitionRegistryPostProcessor
)重新排序MapperScannerConfigurer
?
经过几个小时的调查后,我找到了解决方案:
正如我之前所说,MapperScannerConfigurer
是一个BeanDefinitionRegistryPostProcessor
,它在BeanFactoryPostProcessor
之前触发,负责<context:property-placeholder/>
。因此,在创建MapperScannerConfigurer期间,不会解析对外部属性的引用。在这种情况下,我们必须将数据源的创建推迟到应用BeanFactoryPostProcessor
之后的时间。我们可以通过以下几种方式实现这一目标:
p:sqlSessionFactory-ref="sqlSessionFactory"
移除MapperScannerConfigurer
。在这种情况下,数据源对象不会在MapperScannerConfigurer
之前创建,而是在负责BeanFactoryPostProcessor
的{{1}}之后创建。如果你在applicationContext中有多个sqlSessionFactory,那可能会有些麻烦<context:property-placeholder/>
而不是sqlSessionFactoryBeanName
。它有助于解决sqlSessionFactory
的PropertyPlaceHolder问题。这是解决mybatis-spring doc 答案 0 :(得分:0)
我遇到了同样的问题并且发现了这篇文章,但是我无法像mak那样解决它。最终为我工作的是将ignoreUnresolvablePlaceholders属性值设置为true。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
我也在使用Spring 3.2.3.RELEASE。我发现这篇文章已经超过4个月了,但我认为有人可能觉得它很有用。
答案 1 :(得分:0)
简短形式:加载以下实现的正确方法是什么:BeanDefinitionRegistryPostProcessor?
扩展形式:有没有办法在创建任何bean之前加载BeanDefinitionRegistryPostProcessor。如果你看一下javadoc:
扩展到标准{@link BeanFactoryPostProcessor} SPI,允许 在常规之前注册其他bean定义 BeanFactoryPostProcessor检测开始了。
所以它意味着在创建bean定义时但在创建任何bean之前加载。如果我们只是在应用程序xml中将它创建为常规bean,那么它就会破坏首先使用这个bean的目的。