2010-08-31 18 views
8

現在我可以從財產文件注入值:如何使用Spring框架將屬性文件中的值轉換爲Map?

@Value("${aaa.prop}") 
public String someProp; 

但我想更多的東西......

例如,我有一些屬性文件:

aaa.props=p1,p2,p3 
aaa.props.p1=qwe 
aaa.props.p2=asd 
aaa.props.p3=zxc 

我知道當然,它包含屬性aaa.props,並且對其他屬性一無所知。我想用這樣的符號映射得到這個屬性:

@Value ("${aaa.props}") 
public Map<String, String> someProps; 

所得someProps:{p1=qwe,p2=asd,p3=zxc}

+0

您可能會發現這個問題的答案非常有用:http://stackoverflow.com/questions/9259819/how-to-read-值 - 從屬性文件。將屬性對象注入資源,解析列表1並相應地構建地圖。 – mrembisz 2013-01-17 12:43:24

回答

2

恐怕你不能直接。但是你可以

  • 執行ApplicationContextAware並將ApplicationContext設置爲您的bean中的字段。
  • @PostConstruct方法調用context.getBean("${aaa.props}")
  • 手工解析結果,並將其設置爲所需的領域
+0

有沒有辦法讓所有物業找到我需要的物業? – 2012-10-12 10:38:43

5

好吧,我爲你打造一個通用的方法:一個工廠bean,通過過濾其他地圖創建一個地圖(屬性畢竟是一種地圖)。

這裏的工廠bean:

public class FilteredMapFactoryBean<V> extends 
    AbstractFactoryBean<Map<String, V>>{ 

    private Map<String, V> input; 

    /** 
    * Set the input map. 
    */ 
    public void setInput(final Map<String, V> input){ 
     this.input = input; 
    } 

    /** 
    * Set the string by which key prefixes will be filtered. 
    */ 
    public void setKeyFilterPrefix(final String keyFilterPrefix){ 
     this.entryFilter = new EntryFilter<String, V>(){ 

      @Override 
      public boolean accept(final Entry<String, V> entry){ 
       return entry.getKey().startsWith(keyFilterPrefix); 
      } 
     }; 
    } 

    public static interface EntryFilter<EK, EV> { 

     boolean accept(Map.Entry<EK, EV> entry); 
    } 

    /** 
    * If a prefix is not enough, you can supply a custom filter. 
    */ 
    public void setEntryFilter(final EntryFilter<String, V> entryFilter){ 
     this.entryFilter = entryFilter; 
    } 

    private EntryFilter<String, V> entryFilter; 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    public Class<?> getObjectType(){ 
     return Map.class; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    protected Map<String, V> createInstance() throws Exception{ 
     final Map<String, V> map = new LinkedHashMap<String, V>(); 
     for(final Entry<String, V> entry : this.input.entrySet()){ 
      if(this.entryFilter == null || this.entryFilter.accept(entry)){ 
       map.put(entry.getKey(), entry.getValue()); 
      } 
     } 
     return map; 
    } 

} 

這裏是一個Spring bean定義文件的一些示例用法:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 

    <!-- use System.getProperties() as input --> 
    <bean class="spring.test.FilteredMapFactoryBean" id="javaMap"> 
     <property name="keyFilterPrefix" value="java." /> 
     <property name="input" value="#{T(java.lang.System).getProperties()}" /> 
    </bean> 

    <!-- use custom properties as input --> 
    <bean class="spring.test.FilteredMapFactoryBean" id="customMap"> 
     <property name="keyFilterPrefix" value="hello" /> 
     <property name="input"> 
      <props> 
       <prop key="hello">Is it me you're looking for?</prop> 
       <prop key="hello.again">Just called to say: hello.</prop> 
       <prop key="hello.goodby">You say goodbye and I say hello</prop> 
       <prop key="goodbye.blue.sky">Did-did-did-did-you hear the falling bombs?</prop> 
       <prop key="goodbye.ruby.tuesday">Who could hang a name on you?</prop> 
      </props> 
     </property> 
    </bean> 

</beans> 

,這裏是一個測試類:

public class Tester{ 

    @SuppressWarnings("unchecked") 
    public static void main(final String[] args){ 
     final ApplicationContext context = 
      new ClassPathXmlApplicationContext("classpath:spring/test/mapFactorybean.xml"); 

     final Map<String, String> javaMap = 
      (Map<String, String>) context.getBean("javaMap"); 
     print("java.", javaMap); 
     final Map<String, String> customMap = 
      (Map<String, String>) context.getBean("customMap"); 
     print("hello.", customMap); 

    } 

    private static void print(final String prefix, final Map<String, String> map){ 
     System.out.println("Map of items starting with " + prefix); 
     for(final Entry<String, String> entry : map.entrySet()){ 
      System.out.println("\t" + entry.getKey() + ":" + entry.getValue()); 
     } 
     System.out.println(""); 
    } 

} 

的輸出如預期:

Map of items starting with java. 
    java.runtime.name:Java(TM) SE Runtime Environment 
    java.vm.version:14.2-b01 
    java.vm.vendor:Sun Microsystems Inc. 
    java.vendor.url:http://java.sun.com/ 
    java.vm.name:Java HotSpot(TM) Client VM 
    java.vm.specification.name:Java Virtual Machine Specification 
    java.runtime.version:1.6.0_16-b01 
    java.awt.graphicsenv:sun.awt.Win32GraphicsEnvironment 
     [... etc] 

Map of items starting with hello. 
    hello.goodby:You say goodbye and I say hello 
    hello:Is it me you're looking for? 
    hello.again:Just called to say: hello. 
+0

'AbstractFactoryBean'默認爲單例。在上下文中多次使用這個bean(具有不同的屬性)不會是一個問題嗎? – naXa 2014-09-24 13:25:03

+0

@naXa這個答覆是4歲。這些天FactoryBeans有點不贊成。我會用\ @Configuration類代替 – 2014-09-24 16:29:36

0

你可以做這樣的事情: Maven的依賴

<dependency> 
     <groupId>javax.annotation</groupId> 
     <artifactId>javax.annotation-api</artifactId> 
     <version>1.2</version> 
    </dependency> 

添加導入。

import javax.annotation.Resource; 

...

@Resource (name="propertiesMapName") 
public Properties someProps; 

在Spring XML應用程序上下文:

<util:properties id="propertiesMapName" location="classpath:yourFile.properties"/> 

你會需要這個命名空間

xmlns:util="http://www.springframework.org/schema/util" 

http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util-3.1.xsd 
+0

我可以知道爲什麼我在解決方案中有-1嗎?這工作,我認爲是一個非常乾淨的方式,我想明白什麼是錯的。謝謝 – cralfaro 2016-02-23 09:33:23

1

可以使用@Value

屬性文件:

aaa.props={p1:'qwe',p2:'asd',p3:'zxc'} 

Java代碼:

@Value("#{${aaa.props}}") 
private Map<String,String> someProps; 
+0

這是應該得到upvoted和接受作爲答案。另外,那些使用基於Spring XML的配置的人可以簡單地使用像'p:someProps =「#{$ {aaa.props}}」'這樣的屬性來注入。 – 2017-08-21 12:39:16

相關問題