2010-08-31 4 views
8

Por ahora podía inyectar valores de propiedad-archivos:¿Cómo obtener valores de un archivo de propiedad en Map usando Spring framework?

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

pero quiero algo más ...

Por ejemplo, tengo un poco de archivo de propiedades:

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

Sé que para seguro, que contiene la propiedad aaa.props, y no sabe nada sobre otras propiedades. Y yo quiero conseguir estas propiedades en al mapa utilizando código como este:

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

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

+0

Usted puede encontrar las respuestas a esta pregunta útiles: http://stackoverflow.com/questions/9259819/how-to-read- values-from-properties-file. Inyecte el objeto de propiedades como recurso, analice la lista uno y construya su mapa en consecuencia. – mrembisz

Respuesta

2

me temo que no puede, directamente. Pero se puede

  • aplicar ApplicationContextAware y establecer el ApplicationContext como un campo en el bean.
  • en una llamada @PostConstruct método context.getBean("${aaa.props}")
  • analizar el resultado manualmente y configurarlo para que los campos deseados
+0

¿Hay alguna manera de obtener todas las propiedades para encontrar las que necesito? –

5

Bueno, construyeron un enfoque genérico para usted: un grano de fábrica que crea un mapa mediante el filtrado de otro mapa (las propiedades son un tipo de mapa, después de todo).

Aquí está el grano de la fábrica:

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; 
    } 

} 

Aquí es un archivo de definición de frijol de primavera con algunos ejemplos de uso:

<?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> 

Y aquí hay una clase de prueba:

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(""); 
    } 

} 

El la salida es como se esperaba:

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' es singleton por defecto. ¿No sería un problema usar este bean varias veces (con diferentes propiedades) en un contexto? – naXa

+0

@naXa esta respuesta tiene 4 años. estos días FactoryBeans están un poco desaconsejados. Me gustaría ir con clases \ @Configuration en su lugar –

0

se podría hacer algo como esto: Maven dependencia

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

Añadir la importación.

import javax.annotation.Resource; 

...

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

En el contexto de la aplicación XML primavera:

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

Necesitará este espacio de nombres

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

¿puedo saber por qué tengo -1 en la solución? Esto funciona y creo que es una manera bastante limpia, me gustaría entender qué está mal. Gracias – cralfaro

1

puede utilizar @Value.presentar

Propiedades: Código

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

Java:

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

Esto es lo que debería ser votado y aceptado como la respuesta. Además, aquellos que usan la configuración basada en Spring XML, simplemente pueden inyectar esto usando propiedades como 'p: someProps =" # {$ {aaa.props}} "'. –

Cuestiones relacionadas