1. 程式人生 > >Spring中PropertyPlaceholderConfigurer替換佔位符的問題

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 來排序,因為必須讓最後一個載入的去檢查替換錯誤,之前的都可以不用檢查