2010-08-31 12 views
8

Per ora ho potuto iniettare i valori da proprietà-files:Come ottenere i valori dal file di proprietà in Map usando il framework Spring?

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

Ma io voglio qualcosa di più ...

Per esempio io ho un po 'di file di proprietà:

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

so per certo, che contenga la proprietà aaa.props e non sappia nulla di altre proprietà. E voglio ottenere questo immobili a alla mappa utilizzando il codice in questo modo:

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

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

+0

Si possono trovare le risposte a questa domanda utile: http://stackoverflow.com/questions/9259819/how-to-read- valori-da-proprietà-file. Iniettare l'oggetto proprietà come risorsa, analizzare l'elenco uno e creare la mappa di conseguenza. – mrembisz

risposta

2

ho paura non si può, direttamente. Ma si può

  • implementare ApplicationContextAware e impostare il ApplicationContext come un campo nel bean.
  • in una chiamata di @PostConstruct metodo context.getBean("${aaa.props}")
  • analizzare il risultato manualmente e impostarla i campi desiderati
+0

C'è un modo per ottenere tutte le proprietà per trovare quelle che mi servono? –

5

Beh ho costruito un approccio generico per voi: un fagiolo fabbrica che crea una mappa filtrando un'altra mappa (le proprietà sono una specie di mappa, dopo tutto).

Ecco il fagiolo fabbrica:

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

} 

Ecco un file di definizione di primavera di fagioli con qualche esempio dell'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> 

e qui è una classe di test:

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

} 

Il l'output è come previsto:

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' è singleton per impostazione predefinita. Non sarebbe un problema utilizzare questo bean più volte (con proprietà diverse) in un contesto? – naXa

+0

@naXa questa risposta ha 4 anni. questi giorni i FactoryBeans sono un po 'deprecati. Vorrei andare con le classi \ @Configuration invece –

0

Si potrebbe fare qualcosa di simile: Maven dipendenza

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

Aggiungere l'importazione.

import javax.annotation.Resource; 

...

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

Nel vostro contesto di applicazione xml primavera:

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

Avrete bisogno di questo spazio dei nomi

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

posso sapere perché ho -1 nella soluzione? Questo funziona e penso sia un modo abbastanza pulito, mi piacerebbe capire cosa c'è che non va. Grazie – cralfaro

1

è possibile utilizzare @Value.il file

Proprietà: codice

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

Java:

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

Questo è ciò che dovrebbe essere upvoted e accettato come risposta. Inoltre, coloro che usano la configurazione basata su Spring XML, potrebbero semplicemente inserirli usando proprietà come 'p: someProps =" # {$ {aaa.props}} "'. –

Problemi correlati