SpringBoot加載配置文件(@PropertySource@importSource@Value)


情景描述

最近新搭建了一個項目,從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之后注入的了。

 

附:

@PropertySource API:Resource location wildcards (e.g. **/*.properties) are not permitted; each location must evaluate to exactly one .properties resource.(不允許使用資源位置通配符(例如** / *.屬性);每個位置必須只評估一個.properties資源)

 

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

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


免責聲明!

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



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