1. 程式人生 > 其它 >Spring讀取配置檔案無法解析問題

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"去掉