情況說明
模塊A中Spring 配置文件中注入'a.properties',如下
<context:property-placeholder location="classpath:a.properties"/>
模塊B中Spring 配置文件中注入'b.properties',如下
<context:property-placeholder location="classpath:b.properties"/>
b.properties
中配置如下
person.name=zhangsan
模塊C中Spring 配置文件中注入'c.properties',如下
<context:property-placeholder location="classpath:c.properties"/>
模塊A和模塊B單獨運行都沒問題,但是模塊C集成模塊A與模塊B啟動容器出錯:
Could not resolve placeholder 'person.name' in value "${person.name}"
問題原因
Spring容器采用反射掃描的發現機制,在探測到Spring容器中有一個org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
的Bean就會停止對剩余PropertyPlaceholderConfigurer
的掃描。而<context:property-placeholder/>
這個基于命名空間的配置,其實內部就是創建一個PropertyPlaceholderConfigurer
Bean而已。Spring容器允許定義多個PropertyPlaceholderConfigurer
(或<context:property-placeholder/>
),但定義多個PropertyPlaceholderConfigurer
時默認執行順序是無序的,且在定義第一個PropertyPlaceholderConfigurer
bean的時候,如果沒找到對應的屬性,默認會拋出異常。
即如果先定義的是模塊A中配置器,該配置器只會加載它對應的屬性配置文件,但是此時會掃描整個容器中(模塊A,模塊B...)中的bean,發現有模塊B中定義的bean中的占位符無法解析,直接拋出異常。
解決方式
指定配置器執行順序'order',只讓最后一個配置器解析不了占位符的時候拋出異常,其他的配置器在解析不了占位符時,交給后面的配置器去解析。
模塊A中Spring 配置文件中注入'a.properties',如下
<context:property-placeholder location="classpath:a.properties" order="1" ignore-unresolvable="true"/>
模塊B中Spring 配置文件中注入'b.properties',如下
<context:property-placeholder location="classpath:b.properties" order="2" ignore-unresolvable="true"/>
模塊C中Spring 配置文件中注入'c.properties',如下
<context:property-placeholder location="classpath:c.properties" order="3" ignore-unresolvable="false"/>
參考
關于<context:property-placeholder>的一個有趣現象
鎖定老帖子 主題:關于<context:property-placeholder>的一個有趣現象