Spring讀取配置文件無法解析問題


問題背景:

  • 這個問題排查了有2-3天,嘗試了各種組合配置沒有解決。最后還是查資料看別人的解決經驗解決了。

問題現象:

  • 一個17年的老項目繼續開發,其中是spring+mybatis+ibatis組合,基於一個更早12年的ibatis老項目開發的(開源otter)。把spring的配置datasource的xml文件中datasrouce的driver,url,username,password改成application.properties中使用spring的PropertyPlaceholderConfigurer來進行配置文件讀取值替換。但是怎么配都提示變量無法解析。查了很多材料,都是說PropertyPlaceholderConfigurer的用法和spring怎么配外部配置文件的。沒有關鍵信息、
  • 如果不用配置文件,直接寫死是沒問題的。使用xml中的properties屬性也不行。
  • 錯誤如下圖:
  • 懷疑與bean的初始化順序有關,也就是datasource的bean初始化的時候還沒有進行配置文件解析,PropertyPlaceholderConfigurer還沒生效。

主要探索過程:

  • 首先想到占位符的原理,參考該文章:
    • 深入Spring Boot:那些注入不了的Spring占位符(${}表達式)
    • https://blog.csdn.net/hengyunabc/article/details/75453307
    • 與該文章現象一致,並提示:結合上面的Spring的生命周期,如果Bean的創建和使用在PropertySourcesPlaceholderConfigurer之前,那么就有可能出現占位符沒有被處理的情況。並提出:Mybatis 的 MapperScannerConfigurer引起的占位符沒有處理,查出該類導致了datasource的bean提前初始化,在配置還沒解析前。所以報錯。
    • 大概原因就應該是這個。
  • 繼續探索:
    • 從配置文件PropertySourcesPlaceholderConfigurer何時生效繼續看,找出另一個文章:關於dubbo 占位符無法解析問題
    • https://blog.csdn.net/su20145104009/article/details/105160565
    • 該文提出思路:此時,只有一種想法,難道該 bean 的初始化早於 PropertySourcesPlaceholderConfigurer 的替換?也就是說,RegistryConfig 被提前初始化了
    • 該文提出解決方法:也關注到了:注冊MapperScannerConfigurer的bean被提前初始化的問題
    • 但是改了其中的參數,還是沒解決我的問題。但是排查問題過程更清晰。
  • 繼續探索:
    • 在bing搜索:PropertyPlaceholderConfigurer無法注入,偶然得到一個文章:
    • PropertyPlaceholderConfigurer模式從properties加載數據源參數失敗的解決方案
    • https://www.iteye.com/blog/yjy110-1882876
    • 報錯類似,同時也將問題關注到了:一開始懷疑是spring版本問題,就搜索了一下“spring3 PropertyPlaceholderConfigurer”,結果發現還真有類似的提問,只不過比我問的更准確,一下就把問題定位到了問題的根源-------mybatis下的MapperScannerConfigurer掃描模式造成了bean的加載順序改變從而使得PropertyPlaceholderConfigurer無法正常加載。
      改用sqlSessionFactoryBeanName注入就沒有問題(不要使用sqlSessionFactory屬性注入,使用sqlSessionFactoryBeanName注入),因為這時不會立即初始化sqlSessionFactory,傳入的只是名字,非bean,所以不會引發提前初始化問題。。
    • 該文給出的MapperScannerConfigurer的sqlSessionFactory注入方式也沒解決問題,不過已經可以確認問題就是這個。
    • 文中給出1個鏈接:https://www.oschina.net/question/188964_32305?sort=default&p=3
    • spring3.0.6 使用context:property-placeholder載不進屬性
    • 該問題下面好多人遇到了類似問題,有人提出關鍵點:
    • 兩種解決辦法:
1. <!-- mybatis文件配置,掃描所有mapper文件 -->
<!-- configLocation為mybatis屬性 mapperLocations為所有mapper -->
<bean id="mb-sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" 
  p:dataSource-ref="dataSource" p:configLocation="classpath:web/sqlmap/mybatis-config.xml" 
  p:mapperLocations="classpath:web/sqlmap/mapper/*.xml" />
  <!-- spring與mybatis整合配置,掃描所有dao -->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"p:basePackage="com.jiezhibar.candy.web.dao" 
     p:sqlSessionFactoryBeanName="mb-sqlSessionFactory" />
  即:sqlSessionFactoryBeanName的值寫成非sqlSessionFactory

2、xml 頭部將 default-autowire="byName"去掉


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM