Un guide rapide sur Spring @Value

1. Vue d'ensemble

Dans ce rapide tutoriel, nous allons jeter un œil à l' annotation @Value Spring.

Cette annotation peut être utilisée pour injecter des valeurs dans des champs dans des beans gérés par Spring, et elle peut être appliquée au niveau du champ ou du paramètre du constructeur / méthode.

2. Configuration de l'application

Pour décrire différents types d'utilisation de cette annotation, nous devons configurer une classe de configuration d'application Spring simple.

Naturellement, nous aurons besoin d'un fichier de propriétés pour définir les valeurs que nous voulons injecter avec l' annotation @Value . Et donc, nous devons d'abord définir un @PropertySource dans notre classe de configuration - avec le nom du fichier de propriétés.

Définissons le fichier de propriétés:

value.from.file=Value got from the file priority=high listOfValues=A,B,C

3. Exemples d'utilisation

À titre d'exemple basique et généralement inutile, nous ne pouvons injecter qu'une «valeur de chaîne» de l'annotation dans le champ:

@Value("string value") private String stringValue;

L'utilisation de l' annotation @PropertySource nous permet de travailler avec les valeurs des fichiers de propriétés avec l' annotation @Value .

Dans l'exemple suivant, nous obtenons la valeur obtenue à partir du fichier affecté au champ:

@Value("${value.from.file}") private String valueFromFile;

Nous pouvons également définir la valeur à partir des propriétés système avec la même syntaxe.

Supposons que nous ayons défini une propriété système nommée systemValue :

@Value("${systemValue}") private String systemValue;

Des valeurs par défaut peuvent être fournies pour les propriétés qui peuvent ne pas être définies. Ici, la valeur par défaut sera injectée:

@Value("${unknown.param:some default}") private String someDefault;

Si la même propriété est définie en tant que propriété système et dans le fichier de propriétés, la propriété système sera appliquée.

Supposons que nous ayons une priorité de propriété définie comme propriété système avec la valeur System property et définie comme autre chose dans le fichier de propriétés. La valeur serait la propriété système :

@Value("${priority}") private String prioritySystemProperty;

Parfois, nous devons injecter un tas de valeurs. Il serait pratique de les définir comme des valeurs séparées par des virgules pour la propriété unique dans le fichier de propriétés ou comme une propriété système et de les injecter dans un tableau.

Dans la première section, nous avons défini des valeurs séparées par des virgules dans le listOfValues du fichier de propriétés , de sorte que les valeurs du tableau seraient [“A”, “B”, “C”]:

@Value("${listOfValues}") private String[] valuesArray;

4. Exemples avancés avec SpEL

Nous pouvons également utiliser des expressions SpEL pour obtenir la valeur.

Si nous avons une propriété système nommée priority, sa valeur sera appliquée au champ:

@Value("#{systemProperties['priority']}") private String spelValue;

Si nous n'avons pas défini la propriété système, la valeur nulle sera affectée.

Pour éviter cela, nous pouvons fournir une valeur par défaut dans l'expression SpEL. Nous obtenons une valeur par défaut pour le champ si la propriété système n'est pas définie:

@Value("#{systemProperties['unknown'] ?: 'some default'}") private String spelSomeDefault;

De plus, nous pouvons utiliser une valeur de champ provenant d'autres beans. Supposons que nous ayons un bean nommé someBean avec un champ someValue égal à 10 . Ensuite, 10 seront attribués au champ:

@Value("#{someBean.someValue}") private Integer someBeanValue;

Nous pouvons manipuler les propriétés pour obtenir une liste de valeurs, ici, une liste de valeurs de chaîne A, B et C:

@Value("#{'${listOfValues}'.split(',')}") private List valuesList;

5. Utilisation de @Value avec des cartes

Nous pouvons également utiliser l' annotation @Value pour injecter une propriété Map .

Tout d'abord, nous devons définir la propriété sous la forme {key: 'value'} dans notre fichier de propriétés:

valuesMap={key1: '1', key2: '2', key3: '3'}

Notez que les valeurs de la carte doivent être entre guillemets simples.

Nous pouvons maintenant injecter cette valeur à partir du fichier de propriétés sous forme de carte :

@Value("#{${valuesMap}}") private Map valuesMap;

Si nous avons besoin d'obtenir la valeur d'une clé spécifique dans la carte , tout ce que nous avons à faire est d' ajouter le nom de la clé dans l'expression :

@Value("#{${valuesMap}.key1}") private Integer valuesMapKey1;

Si nous ne savons pas si la carte contient une certaine clé, nous devons choisir une expression plus sûre qui ne lèvera pas d'exception mais définira la valeur sur null lorsque la clé n'est pas trouvée:

@Value("#{${valuesMap}['unknownKey']}") private Integer unknownMapKey;

Nous pouvons également définir des valeurs par défaut pour les propriétés ou les clés qui peuvent ne pas exister :

@Value("#{${unknownMap : {key1: '1', key2: '2'}}}") private Map unknownMap; @Value("#{${valuesMap}['unknownKey'] ?: 5}") private Integer unknownMapKeyWithDefaultValue;

Les entrées de carte peuvent également être filtrées avant l'injection.

Supposons que nous ayons besoin d'obtenir uniquement les entrées dont les valeurs sont supérieures à un:

@Value("#{${valuesMap}.?[value>'1']}") private Map valuesMapFiltered;

Nous pouvons également utiliser l' annotation @Value pour injecter toutes les propriétés système actuelles :

@Value("#{systemProperties}") private Map systemPropertiesMap;

6. Utilisation de @Value avec l'injection de constructeur

When we use the @Value annotation, we're not limited to a field injection. We can also use it together with constructor injection.

Let's see this in practice:

@Component @PropertySource("classpath:values.properties") public class PriorityProvider { private String priority; @Autowired public PriorityProvider(@Value("${priority:normal}") String priority) { this.priority = priority; } // standard getter }

In the above example, we inject a priority directly into our PriorityProvider‘s constructor.

Note that we also provide a default value in case the property isn't found.

7. Using @Value With Setter Injection

Analogous to the constructor injection, we can also use @Value with setter injection.

Let's take a look:

@Component @PropertySource("classpath:values.properties") public class CollectionProvider { private List values = new ArrayList(); @Autowired public void setValues(@Value("#{'${listOfValues}'.split(',')}") List values) { this.values.addAll(values); } // standard getter }

We use the SpEL expression to inject a list of values into the setValues method.

8. Conclusion

Dans cet article, nous avons examiné les différentes possibilités d'utilisation de l' annotation @Value avec des propriétés simples définies dans le fichier, avec des propriétés système et avec des propriétés calculées avec des expressions SpEL.

Comme toujours, l'exemple d'application est disponible sur le projet GitHub.