最近有朋友問@Value注入Properties數據注入不進去,接下來我就分析一下爲什麼。
場景:
需要注入Properties的value數據到Bean或方法參數。
準備數據:
<bean id="props" class="java.util.Properties">
<constructor-arg index="0">
<props>
<prop key="a">123</prop>
</props>
</constructor-arg>
</bean>
<bean id="map" class="java.util.HashMap">
<constructor-arg index="0">
<map>
<entry key="a" value="234"/>
</map>
</constructor-arg>
</bean>
失敗的做法:
@Value("#{props['a']}")
private String propsA;
此時無法獲取props的a這個鍵對應的值。
正確的做法:
@Value("#{props.getProperty('a')}")
private String propsA;
@Value("#{map['a']}")
private String mapA;
@RequestMapping(value="/value2")
public String test2(@Value("#{props.getProperty('a')}") String propsA, @Value("#{map['a']}") String mapA) {
爲什麼?最後探討。
最好的正確做法:
<util:properties id="props2">
<prop key="a">123</prop>
</util:properties>
//該標籤內部使用org.springframework.beans.factory.config.PropertiesFactoryBean FactoryBean實現;
@Value("#{props2['a']}") String props2A,
注入數據直接使用props[key]即可。
why?
爲什麼如下方式不行:
<bean id="props" class="java.util.Properties">
<constructor-arg index="0">
<props>
<prop key="a">123</prop>
</props>
</constructor-arg>
</bean>
而如下這種方式行呢?
<util:properties id="props2">
<prop key="a">123</prop>
</util:properties>
原因很簡單:API不熟造成的:
1、首先我們來看下Properties構造器定義:
參數:
defaults - 默認值。
1)、構造器第一個參數是默認值;
2)、當我們使用getProperty(key) 時,首先查自己的prop,如果有直接返回,否則查defaults中的key。
用指定的鍵在此屬性列表中搜索屬性。如果在此屬性列表中未找到該鍵,則接着遞歸檢查默認屬性列表及其默認值。如果未找到屬性,則此方法返回 null。
2、而使用<util:properties id="props2"> 本身是一個FactoryBean,幫我們創建沒有我們真實需要的properties。有興趣可以看下源代碼。
總結:
1、API不熟造成了錯誤理解(以爲類似於如集合框架是做拷貝);
2、Properties繼承Hashtable本身就是一種錯誤的繼承,形成兩套不同的API。