MapperScannerConfigurer

MapperScannerConfigurer

本文介绍了context:property-placeholder无法解析引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在类路径的根目录下有下一个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 BeanFactoryPostProcessorhave 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" from MapperScannerConfigurer. In this case datasource object will not be created before MapperScannerConfigurer, but after BeanFactoryPostProcessor 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 of sqlSessionFactory. It helps to resolve PropertyPlaceHolder issue with BeanFactoryPostProcessor. 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无法解析引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 16:28