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

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