2010-08-31 47 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

相关问题