Spring讀取配置檔案無法解析問題
阿新 • • 發佈:2022-01-06
問題背景:
- 這個問題排查了有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"去掉
-
發現我的專案裡確實有default-autowire="byName"去掉後圓滿解決,datasource的引數可以正常注入了。
-
dubbo consumer讀取配置檔案無法解析問題
- 參考:https://blog.csdn.net/u011494923/article/details/88076096
- dubbo的xml中${}不生效獲取不到變數
-
參考:spring配置檔案:Could not resolve placeholder
-
參考:PropertySourcesPlaceholderConfigurer讀取配置檔案的坑
- https://blog.csdn.net/leaves_story/article/details/89672050
- 該文說明:Spring容器僅允許最多定義一個PropertyPlaceholderConfigurer(或),其餘的會被Spring忽略掉。
-
參考:Spring 在xml中引入properties檔案方式和問題
-
參考:Spring 常用的兩種PropertyPlaceholderConfigurer