Spring中PropertyPlaceholderConfigurer替換佔位符的問題
最近在做專案的時候,碰到了一個問題,糾結了好久,現在記錄一下
問題
多個Maven專案聚合的時候,每個maven都有自己的配置檔案,並且都用了PropertyPlaceholderConfigurer替換佔位符,然後啟動的時候一直報錯,說替換失敗;問題癥結就是 spirng配置多個PropertyPlaceholderConfigurer的問題
原因
在spring bean裝配時,一個PropertyPlaceholderConfigurer就是一個後置處理器BeanFactoryPostProcessor。在裝配完PropertyPlaceholderConfigurer之後,就會觸發org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Collection
/**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
假設一下,你配置了兩個PropertyPlaceholderConfigurer例項
A模板的jdbc.xml配置檔案
<bean id="propertyConfigurer" class="com.zheng.common.plugin.EncryptPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value >
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
B模板的shiro.xml配置檔案
<context:property-placeholder location="classpath*:zheng-upms-client.properties"/>
然後A模板中的jdbc.properties 和 B中的zheng-upms-client.properties 檔案都在A模板中;
A依賴了B;啟動A專案,IOC會先例項化這兩個配置的PropertyPlaceholderConfigurer;
假如先例項化了A中的PropertyPlaceholderConfigurer例項,那麼它會去替換所有被標記為 ${} 的佔位符,這個時候替換到B模板中的一些佔位符之後,肯定就會報錯了,因為B模板中的佔位符是在 zheng-upms-client.properties這個屬性檔案中;
解決方案
一、使用一個PropertyPlaceholderConfigurer例項載入
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
<value>classpath:zheng-upms-client.properties</value>
</list>
</property>
</bean>
但是這樣解決真的是超級沒有誠意了,本來就是解決不通模組之間的問題啊
二、配置載入順序,並設定替換失敗不報錯
1.讓B中的例項配置order=1 先載入,並且設定ignore-unresolvable=”true”表示替換失敗不報錯
<context:property-placeholder order="1" ignore-unresolvable="true" location="classpath*:zheng-upms-client.properties"/>
2.設定A中,order=2 表示後加載,但是不設定ignore-unresolvable屬性,因為最後還是要檢查是否有剩餘未替換的屬性
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="2" />
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
總結
思路就是 當有多個例項的時候,讓他們一個一個的去替換,替換失敗不提示錯誤,等做後一個例項替換的時候如果還有沒有被替換的就提示錯誤!
所以要設定 order 來排序,因為必須讓最後一個載入的去檢查替換錯誤,之前的都可以不用檢查