2012-07-10 29 views
30

Estoy leyendo el archivo de propiedades usando context:property-placeholder. ¿Cómo puedo acceder a ellos programáticamente (@Value no funciona - No conozco los títulos de propiedad en el momento del desarrollo)?Acceso programático a las propiedades creadas por el marcador de posición de la propiedad

El principal problema es que no puedo cambiar applicationContext.xml archivo porque está setted por el "padre" marco

ps. Es extraño pero Environment.getProperty devuelve null

+0

Ver http: // stackoverflow.com/questions/5172392/how-to-programmatically-resolve-property-placeholder-in-spring. Parece posible desde la primavera 3. – Vadzim

Respuesta

28

No, no puedes. PropertyPlaceholderConfigurer es BeanFactoryPostProcessor, solo está "vivo" durante la creación del frijol. Cuando encuentra una notación ${property}, intenta resolver eso contra sus propiedades internas, pero no pone estas propiedades disponibles para el contenedor.

Dicho esto: las preguntas similares han aparecido una y otra vez, la solución propuesta es generalmente to subclass PropertyPlaceHolderConfigurer y pone las Propiedades a disposición del contexto manualmente. O use a PropertiesFactoryBean

4

El resorte sigue el enfoque de Inversión de control, esto significa que podemos simplemente inyectar una propiedad particular en POJO. Pero en algunos casos, cuando le gustaría acceder a propiedades dadas por nombre directamente desde su código, algunos lo pueden ver como antipatrón (patrón), esto es palpablemente cierto, pero centrémonos en cómo hacerlo.

El PropertiesAccessor a continuación proporciona acceso a las propiedades cargadas por Property Placeholder y encapsula cosas específicas del contenedor. También almacena en caché las propiedades encontradas porque llamar al AbstractBeanFactory#resolveEmbeddedValue(String) no es barato.

@Named 
public class PropertiesAccessor { 

    private final AbstractBeanFactory beanFactory; 

    private final Map<String,String> cache = new ConcurrentHashMap<>(); 

    @Inject 
    protected PropertiesAccessor(AbstractBeanFactory beanFactory) { 
     this.beanFactory = beanFactory; 
    } 

    public String getProperty(String key) { 
     if(cache.containsKey(key)){ 
      return cache.get(key); 
     } 

     String foundProp = null; 
     try { 
      foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");   
      cache.put(key,foundProp);   
     } catch (IllegalArgumentException ex) { 
      // ok - property was not found 
     } 

     return foundProp; 
    } 
} 
9
@Value 

anotación trabaja en las nuevas versiones de la primavera (probado en V3.2.2) Aquí es cómo se hace:

  1. Mapa archivo de propiedades en el archivo de configuración del resorte

    <!--Import Info: 
    xmlns:context="http://www.springframework.org/schema/context" 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd--> 
    
    <context:property-placeholder location="classpath:/app-config.properties" /> 
    
  2. Crea app-config.properties dentro (raíz) de tu carpeta de origen

    my.property=test 
    my.property2=test2 
    
  3. crear una clase controlador

    @Controller 
    public class XRDSBuilder 
    { 
        @Value("${my.property}") 
        private String myProperty; 
    
        public String getMyProperty() { return myProperty; } 
    } 
    

primavera se asignarán de forma automática el contenido de mi.propiedad a la variable dentro del controlador

Mapping to a list

Valor de la propiedad:

my.list.property=test,test2,test3 

controlador de configuración de clases:

@Value("#{'${my.list.property}'.split(',')}") 
private List<String> myListProperty; 

Advanced mapping

@Component("PropertySplitter") 
public class PropertySplitter { 

    /** 
    * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2 
    */ 
    public Map<String, String> map(String property) { 
     return this.map(property, ","); 
    } 

    /** 
    * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2 
    */ 
    public Map<String, List<String>> mapOfList(String property) { 
     Map<String, String> map = this.map(property, ";"); 

     Map<String, List<String>> mapOfList = new HashMap<>(); 
     for (Entry<String, String> entry : map.entrySet()) { 
      mapOfList.put(entry.getKey(), this.list(entry.getValue())); 
     } 

     return mapOfList; 
    } 

    /** 
    * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4 
    */ 
    public List<String> list(String property) { 
     return this.list(property, ","); 
    } 

    /** 
    * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2 
    */ 
    public List<List<String>> groupedList(String property) { 
     List<String> unGroupedList = this.list(property, ";"); 

     List<List<String>> groupedList = new ArrayList<>(); 
     for (String group : unGroupedList) { 
      groupedList.add(this.list(group)); 
     } 

     return groupedList; 

    } 

    private List<String> list(String property, String splitter) { 
     return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property); 
    } 

    private Map<String, String> map(String property, String splitter) { 
     return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property); 
    } 
} 

Valor de la propiedad:

my.complex.property=test1:value1,test2:value2 

Controlador de la clase:

@Value("#{PropertySplitter.map('${my.complex.property}')}") 
Map<String, String> myComplexProperty; 
+1

Esto no responde a la pregunta tal como se establece. – Joel

+0

Respuesta perfecta :) – Manoj

+0

¿Funciona eso con el tiempo de ejecución de curren Mule ESB 3.7.3? No puedo llegar a una solución con eso, me está dando un error como 'Error al convertir el valor de propiedad del tipo 'java.util.ArrayList' al tipo requerido 'java.util.List' para la propiedad 'messageProcessors'' – Hayra

2

respuesta Encontrado por debajo sitio:

http://forum.spring.io/forum/spring-projects/container/106180-programmatic-access-to-properties-defined-for-the-propertyplaceholderconfigurer

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer"> 
<property name="properties" ref="props" /> 
</bean> 
<bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
    <property name="location" value="file:C:/CONFIG/settings.properties"/> 
</bean> 
6

Usamos el siguiente enfoque acceder a las propiedades de nuestra aplicaciones

<util:properties id="appProperties" location="classpath:app-config.properties" /> 
<context:property-placeholder properties-ref="appProperties"/> 

Luego puede darse el lujo de autoaumentar las propiedades de los frijoles utilizando un calificador.

@Component 
public class PropertyAccessBean { 

    private Properties properties; 

    @Autowired 
    @Qualifier("appProperties") 
    public void setProperties(Properties properties) { 
     this.properties = properties; 
    } 

    public void doSomething() { 
     String property = properties.getProperty("code.version"); 
    } 

} 

Si tiene propiedades más complejas, puede seguir utilizando ignore-resource-not-found e ignore-unresolvable. Utilizamos este enfoque para externalizar algunas de las configuraciones de nuestra aplicación.

<util:properties id="appProperties" ignore-resource-not-found="true" 
    location="classpath:build.properties,classpath:application.properties, 
          file:/data/override.properties"/> 
<context:property-placeholder ignore-unresolvable="true" properties-ref="appProperties"/> 
-1

ASUME Vamos que el archivo de propiedades se definen en ese marco "padre"

<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
    <property name="location" value="classpath:main.properties" /> 
</bean> 

Puede utilizar la anotación @Valor de esta manera:

@Value(value = "#{applicationProperties['my.app.property']}") 
private String myProperty; 
+0

Se encuentra con un error en Spring 4: No se admite la indexación en el tipo 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' –

+0

Like @SeanPatrickFloyd comentó: "_similares preguntas han aparecido nuevamente y nuevamente, la solución propuesta suele ser la subclase PropertyPlaceHolderConfigurer y hacer que las Propiedades estén disponibles para el contexto de forma manual. O bien, use ** PropertiesFactoryBean ** _ ". Espero que esto te ayude: [Reading-valued-from-properties-file-at-Runtime] (https://stackoverflow.com/questions/5665296/reading-valued-from-properties-file-at-runtime/5673678# 5673678) –

Cuestiones relacionadas