Spring的屬性文件properties使用注意
Spring 中屬性文件的配置
通常我們會使用properties文件來設置一些屬性,如數據庫連接信息,避免進行硬編碼,
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
//if you want you can add more here.
</list>
</property>
</bean>
或 在Spring 3.1.x. 之后使用 PropertySourcesPlaceholderConfigurer
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
//if you want you can add more here.
</list>
</property>
</bean>
來源: http://stackoverflow.com/questions/28040889/spring-mvc-could-not-resolve-placeholder-in-string-value
更簡潔的方法是使用
<context:property-placeholder location="classpath*:config/db.properties" />
問題
在一個多模塊maven項目中,不同的模塊需要不同的屬性配置,因此使用context:property-placeholder
配置了兩個properties文件:db.properties
和 email.properties
,但程序啟動時遇到下述錯誤
caused by java.lang.illegalargumentexception could not resolve placeholder 'mail.sender.password' in string value ${mail.sender.password}
即不能處理第二個屬性文件中的配置信息!
因為Spring不允許定義多個PropertyPlaceholderConfigurer
或<context:property-placeholder/>
!
spring中 context:property-placeholder 導入多個獨立的 .properties配置文件?
Spring容器采用反射掃描的發現機制,在探測到Spring容器中有一個org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
的 Bean就會停止對剩余PropertyPlaceholderConfigurer
的掃描(Spring 3.1已經使用PropertySourcesPlaceholderConfigurer
替代PropertyPlaceholderConfigurer
了)。
換句話說,即Spring容器僅允許最多定義一個PropertyPlaceholderConfigurer
(或<context:property-placeholder/>
),其余的會被Spring忽略掉(其實Spring如果提供一個警告就好了)。
拿上來的例子來說,如果A和B模塊是單獨運行的,由於Spring容器都只有一個PropertyPlaceholderConfigurer
, 因此屬性文件會被正常加載並替換掉。如果A和B兩模塊集成后運行,Spring容器中就有兩個PropertyPlaceholderConfigurer
Bean了,這時就看誰先誰后了, 先的保留,后的忽略!因此,只加載到了一個屬性文件,因而造成無法正確進行屬性替換的問題。
來源: http://blog.csdn.net/yu870646595/article/details/50979338
問題的解決方案
方案1:通配符解決、逗號分隔
使用通配符讓spring一次性讀取多個屬性文件到一個 PropertyPlaceholderConfigurer
bean中
<context:property-placeholder location="classpath*:conf/*.properties"/>
來源: http://blog.csdn.net/yu870646595/article/details/50979338
或者使用
<context:property-placeholder location="classpath*:conf/db.properties,conf/email.properties"/>
注意: 如果后一個文件中有和前面某一個文件中屬性名是相同的,最終取的值是后加載的值
方案2:一個PropertySourcesPlaceholderConfigurer中包含多個屬性文件,和方案1原理相同
<bean id="propertyConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>classpath:email.properties</value>
</list>
</property>
方案3:使用 ignore-unresolvable
如果一定要分開定義,則在每個PropertySourcesPlaceholderConfigurer
配置中添加
<property name="ignoreUnresolvablePlaceholders" value="true"/>
或者在每個context:property-placeholder
中都加上ignore-unresolvable="true"
因為在你使用@Value("${xx}")
或在xml中使用${xx}
獲取屬性時,Spring會在第一個讀取到的屬性文件中去找,如果沒有就直接拋出異常,而不會繼續去第二個屬性文件中找
http://stackoverflow.com/questions/18697050/multiple-spring-propertyplaceholderconfigurer-at-the-same-time
http://stackoverflow.com/questions/26657521/spring-multiple-propertyplaceholderconfigurer-in-multiple-projects-how-to-over
http://stackoverflow.com/questions/30616480/spring-value-could-not-resolve-placeholder-in-string-value