1. 程式人生 > >spring4中@value在子父容器中使用時遇到的問題

spring4中@value在子父容器中使用時遇到的問題

@Value作用:獲取配置檔案的值。
注入值:在Spring容器初始化(所有的bean)之後,在當前的所在容器中獲取值,然後注入。
@value是通過${}佔位符去匹配載入到的配置檔案中的鍵值對的鍵

通過以下配置來載入資原始檔

<bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <!-- 允許JVM引數覆蓋 -->
        <property name="systemPropertiesModeName"
value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略沒有找到的資原始檔 --> <property name="ignoreResourceNotFound" value="true" /> <property name="order" value="1"></property> <!-- 配置資原始檔 --> <property name="locations"> <list
>
<value>classpath:env.properties</value> </list> </property> </bean>

但是此配置是配置在springMVC中,springMVC在此專案中為子容器,而父容器中配置了資料庫連線資原始檔,各自用各自的配置,但是在控制層通過佔位符${屬性名}注入子容器屬性時會丟擲異常

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'REPOSITORY_PATH'
in string value "${REPOSITORY_PATH}"

java.lang.IllegalArgumentException:字面意思是非法引數
但通常情況是找不到檔案會丟擲此異常
而這裡
Could not resolve placeholder 'REPOSITORY_PATH' in string value "${REPOSITORY_PATH}"
意思是因為在控制層注入了${REPOSITORY_PATH},但是在父容器中無法解決這個REPOSITORY_PATH字串,所以無法解析此佔位符而丟擲了異常

針對這個錯誤,並沒有去剖析底層程式碼。而是進行了測試
[
假設兩個資原始檔

    A.properties、B.properties
    A.properties中有a = 1、b = 2、c = 3
    B.properties中有c = 1、b = 3、e = 3

使用這兩個資原始檔在子父容器中進行測試
一、在子父容器中分別都注入A、B
執行不會丟擲異常並且成功載入所有資源
二、在子父容器中各自注入其中一個
1呼叫子容器屬性時會丟擲異常
2呼叫父容器屬性時正常
3在呼叫子容器中和父容器中共有的屬性時不會跑出異常,但屬性值會被子容器的值覆蓋
綜上所以得到結論
spring載入配置檔案後會根據配置位置不同分別以將其內容以鍵值對的形式存在各自的容器中
父容器不能訪問子容器的資源,子容器可以訪問父容器的,但是@value又只能匹配本容器的資源,所以在子容器中匹配父容器中不存在的鍵會丟擲上面的異常

${鍵} 的匹配方式,先去父容器儲存鍵值對的地方去進行匹配,如果匹配不到則丟擲異常

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder '鍵' in string value "${鍵}"

解決方案
1、在父容器配置中加入屬性

<!-- 忽略無法解決的佔位符 -->
        <property name="ignoreUnresolvablePlaceholders" value="true" />

這個屬性可以再即使父容器匹配不到的時候也不會丟擲異常 繼續去子容器中進行匹配
2、將子父容器中都載入資原始檔,這樣做比較浪費資源並且有廢操作,比較業餘、勝在方便
3、都在父容器中載入,在父容器的類中得到以後再注入到子容器中的類中,但這樣會常見多餘的物件

所以推薦使用第一種解決方案。。。

其他屬性

<!-- <bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <!-- 允許JVM引數覆蓋 -->
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="order" value="2"></property>
        <!-- 忽略資源未找到
            這個屬性可以忽略不存在的資原始檔
         -->
        <property name="ignoreResourceNotFound" value="true" />
        <!-- 忽略無法解決的佔位符 -->
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <!-- 配置資原始檔 -->
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
            </list>
        </property>
    </bean> -->