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
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
@Value
l'annotation fonctionne sur les nouvelles versions de Spring (testée sur la v3.2.2) Voici comment cela est fait:
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" />
Créez app-config.properties à l'intérieur (racine) de votre dossier source
my.property=test
my.property2=test2
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.
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;
@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;
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"/>
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;
}
}
Réponse trouvée sur le site ci-dessous:
<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>
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")
<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");