MapperScannerConfigurer导致PlaceHolder的替换变量报错

前提

1.开启了byName自动注入
2.定义了PropertySourcesPlaceholderConfigurer,去解析配置。
3.含有id="sqlSessionFactory"的SqlSessionFactory
4.定义了MapperScannerConfigurer,在其属性sqlSessionFactory中的dataSource属性中使用了${username}${password}等。

原因

  1. MapperScannerConfigurer 是一个BeanDefinitionRegistryPostProcessor,它是BeanFactoryPostProcessor的实现类。

  2. PropertySourcesPlaceholderConfigurer是一个BeanFactoryPostProcessor的实现类。

  3. MapperScannerConfigurerPropertySourcesPlaceholderConfigurer 之前被实例化。
    3.1. 这是因为它们会在Spring的refresh->invokeBeanFactoryPostProcessors(beanFactory)被调用。 而顺序是 先注册BeanDefinitionFactoryProcessor,再注册BeanFactoryPostProcessor

  4. MapperScannerConfigurer优先实例化的时候,开启了default-autowire="byName"会连同属性sqlSessionFactory一起初始化,并造成dataSource初始化, 那么${username}被提前设置到dataSource中的username属性中,但此时PropertySourcesPlaceholderConfigurer还未生成实例,更没有替换${username},导致错误!
    4.1 开启default-autowire="byName"自动注入后,会解析出需要"sqlSessionFactory"依赖,并提前初始化。

解决

由于无法改变MapperScannerConfigurer与PropertySourcesPlaceholderConfigurer的getBean初始化顺序。
那么避免sqlSessionFactory的属性提前初始化。
1.去掉default-autowire="byName"
2.改变sqlSessionFactory的id。(未验证) (TODO)

常见报错配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
      http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
      default-autowire="byName">

    <context:property-placeholder location="conf/*.properties"/>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="mapperLocations" value="mapper/*.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.yanmushi.**.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
	
</beans>

参考

https://my.oschina.net/u/161336/blog/1830816

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章