@Value注入Properties 使用錯誤的案例

最近有朋友問@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構造器定義:

javadoc 寫道
public Properties(Properties defaults)創建一個帶有指定默認值的空屬性列表。 

參數:
defaults - 默認值。

 

    1)、構造器第一個參數是默認值;

    2)、當我們使用getProperty(key) 時,首先查自己的prop,如果有直接返回,否則查defaults中的key。

javadoc 寫道
public String getProperty(String key)
用指定的鍵在此屬性列表中搜索屬性。如果在此屬性列表中未找到該鍵,則接着遞歸檢查默認屬性列表及其默認值。如果未找到屬性,則此方法返回 null。
3)、原因到此很明顯了,此時我們使用#{props.getProperty('a')} 其實是查的defaults
4)、Properties本身繼承了Hashtable,其實是一種錯誤的用法,造成了我們現在的我們現在的問題,get(key)只查自己,而getProperty會先查自己 再查defaults。

 

2、而使用<util:properties id="props2"> 本身是一個FactoryBean,幫我們創建沒有我們真實需要的properties。有興趣可以看下源代碼。

 

 

總結:

1、API不熟造成了錯誤理解(以爲類似於如集合框架是做拷貝);

2、Properties繼承Hashtable本身就是一種錯誤的繼承,形成兩套不同的API。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章