web-dev-qa-db-fra.com

Accès par programme aux propriétés créées par property-placeholder

Je lis le fichier de propriétés en utilisant context:property-placeholder. Comment puis-je y accéder par programme (@Value ne fonctionne pas - je ne connais pas les titres de propriété au moment de la création)?

Le problème principal est que je ne peux pas modifier le fichier applicationContext.xml car il est configuré par le cadre "parent".

ps. C'est étrange mais Environment.getProperty renvoie null

36
fedor.belov

Non tu ne peux pas. PropertyPlaceholderConfigurer est un BeanFactoryPostProcessor , il est seulement "vivant" lors de la création du bean. Lorsqu'il rencontre une notation ${property}, il tente de résoudre ce problème par rapport à ses propriétés internes, mais ne rend pas ces propriétés disponibles pour le conteneur.

Cela dit: des questions similaires sont apparues maintes et maintes fois, la solution proposée est généralement de à la sous-classe PropertyPlaceHolderConfigurer et rend les propriétés disponibles au contexte manuellement. Ou utilisez une PropertiesFactoryBean

34
Sean Patrick Floyd
@Value

l'annotation fonctionne sur les nouvelles versions de Spring (testée sur la v3.2.2) Voici comment cela est fait:

  1. Mappez votre fichier de propriétés dans le fichier de configuration de printemps

    <!--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. Créez app-config.properties à l'intérieur (racine) de votre dossier source

    my.property=test
    my.property2=test2
    
  3. Créer une classe de contrôleur

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

Spring mappera automatiquement le contenu de my.property à votre variable dans le contrôleur.

Correspondance à une liste

Valeur de la propriété:

my.list.property=test,test2,test3

Configuration de la classe de contrôleur:

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

Cartographie avancée

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

Valeur de la propriété:

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

Classe de contrôleur:

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

Nous utilisons l'approche suivante pour accéder aux propriétés de nos applications

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

Ensuite, vous avez le luxe de simplement transférer automatiquement des propriétés dans des haricots à l'aide d'un qualificateur.

@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 vous avez des propriétés plus complexes, vous pouvez toujours utiliser ignorer-ressource-introuvable et ignorer-insoluble. Nous utilisons cette approche pour externaliser certains de nos paramètres d'application.

 <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"/>
7
mattyboy

Spring suit l’approche Inversion Of Control, cela signifie que nous pouvons simplement injecter une propriété particulière dans POJO. Cependant, dans certains cas, vous souhaitez accéder à une propriété donnée par son nom directement à partir de votre code - certains pourraient le considérer comme un anti-motif - ceci est manifestement vrai, mais nous allons nous concentrer sur la façon de le faire.

La PropertiesAccessor ci-dessous donne accès aux propriétés chargées par Property Placeholder et encapsule les éléments spécifiques au conteneur. Il met également en cache les propriétés trouvées, car l'appel de AbstractBeanFactory#resolveEmbeddedValue(String) n'est pas bon marché.

@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; 
    } 
}
5
Maciej Miklas

Réponse trouvée sur le site ci-dessous:

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

<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>
2
Sandeep

Créez des haricots pour vos propriétés avant de les placer dans un espace réservé propriété afin de faciliter l'accès aux propriétés dans le code. 

Ex:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="resources" value="classpath:META-INF/spring/config.properties" />
</bean>

<context:property-placeholder properties-ref="configProperties" ignore-unresolvable="true"/>

Code:

@Autowired
private PropertiesFactoryBean configProperties;

Vous pouvez également utiliser @Resource (name = "configProperties")

0
TheJeff
<util:properties id="prop" location="location of prop file" />

Cet objet Java.util.Properties de retour

En code Java

Properties prop = (Properties) context.getBean("prop");

Maintenant, vous pouvez accéder,

prop.getProperty("key");
0
Sarang