SpringBoot載入配置檔案(@PropertySource@importSource@Value)

Boblim發表於2019-06-21

情景描述

最近新搭建了一個專案,從Spring遷到了Springboot,為了相容Spring載入配置檔案的風格,所以還想把PropertyPlaceholderConfigurer放在.xml檔案裡面,然後通過@importSource來載入.xml檔案將配置載入到spring環境中,通過@value或者PropertyUtil來引入對應配置的值。於是發現了以下問題,並根據這些問題進行了問題擴充。

問題描述

1.在.xml引入PropertyPlaceholderConfigurer時,若專案中存在@PropertySource註解,@ConfigurationProperties可以正常載入PropertySource中的配置(啟動時發現Bean正常),但是@Value會在啟動時報錯解析不了佔位符;若@ConfigurationProperties載入的是.xml中配置檔案的值,則也為空。

2.在使用PropertyUtil(由.xml載入配置)時發現,在通過.xml載入配置的這個方法上,public static 變數在@Configuration的配置類通過PropertyUtil獲取配置值時PropertyUtil還未載入(值為null),在其他@Component(包括@Controller)中是可以正常獲取到值(說明已經載入)。

解決方案&原理分析

問題1:

其中@PropertySource註解管理的所有配置檔案相當於一個PropertyPlaceholderConfigurer,只不過是Springboot自己管理的,而.xml中的PropertyPlaceholderConfigurer又是一個,這就會出現多個PropertyPlaceholderConfigurer的問題(目測是由於先載入了@ImportSource中.xml的PropertyPlaceholderConfigurer導致該問題),多PropertyPlaceholderConfigurer問題原因如下:

在spring bean裝配時,一個PropertyPlaceholderConfigurer就是一個後置處理器BeanFactoryPostProcessor。在裝配完PropertyPlaceholderConfigurer之後,就會觸發org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor>, ConfigurableListableBeanFactory)方法,程式碼如下:

複製程式碼
/**
 * Invoke the given BeanFactoryPostProcessor beans.
 */
private void invokeBeanFactoryPostProcessors(
        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}
複製程式碼

每呼叫完一個BeanFactoryPostProcessor之後,就會去解析所有的bean中引用properties的佔位符,這時就會出現佔位符不能解析的問題(不能解析的佔位在後面的BeanFactoryPostProcessor中,也就是PropertyPlaceholderConfigurer例項)。

而在使用@Value時,由於使用了佔位符,而.xml中的PropertyPlaceholderConfigurer先載入解析佔位符但是該配置未存在,所以會報錯佔位符解析失敗。

而使用@ConfigurationProperties時,並沒有使用佔位符,所以如果是在@PropertySource中的配置可以正常載入

但是我個人理解@ConfigurationProperties載入配置是用的@PropertySource的PropertyPlaceholderConfigurer,所以如果配置不是用@PropertySource載入,則載入結果為null(建議配套使用)

解決方法:

<property name="ignoreUnresolvablePlaceholders" value="true"/>

加上上面的一行,表示可以忽略未解析到的佔位符。這樣就不會報錯。

 

問題2:

我理解@Confituration標識的配置類是在@ImportSource載入.xml之前檔案開始載入的,所以它的static值在從PropertyUtil獲取值時,PropertyUtil並沒有載入配置,所以都為空,但是@Component也即bean載入是在@ImportSource之後的,所以static變數可以獲取到正常值。
經過試驗,我發現@Value在@Configuration標識的配置類中是可以正常獲取到.xml載入的值的,這樣表明@Value應該是在@ImportSource之後注入的了。

 

如果對我上面的分析存在異議歡迎討論啊,希望相互提高。

轉載請註明:https://www.cnblogs.com/fnlingnzb-learner/p/11067338.html

相關文章