Перейти к основному содержимому

Краткое руководство по аннотации @Value в Spring

· 5 мин. чтения

1. Обзор

В этом кратком руководстве мы рассмотрим аннотацию @Value Spring.

Эту аннотацию можно использовать для ввода значений в поля в компонентах, управляемых Spring, и ее можно применять на уровне параметров поля или конструктора/метода.

2. Настройка приложения

Чтобы описать различные виды использования этой аннотации, нам нужно настроить простой класс конфигурации приложения Spring.

Естественно, нам понадобится файл свойств для определения значений, которые мы хотим внедрить с помощью аннотации @Value . Итак, сначала нам нужно определить @PropertySource в нашем классе конфигурации — с именем файла свойств.

Давайте определим файл свойств:

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

3. Примеры использования

В качестве базового и в основном бесполезного примера мы можем ввести только «строковое значение» из аннотации в поле:

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

Использование аннотации @PropertySource позволяет нам работать со значениями из файлов свойств с аннотацией @Value .

В следующем примере мы получаем значение, полученное из файла, назначенного полю:

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

Мы также можем установить значение из системных свойств с тем же синтаксисом.

Предположим, что мы определили системное свойство с именем systemValue :

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

Для свойств, которые могут не быть определены, могут быть предоставлены значения по умолчанию. Здесь будет введено значение по умолчанию :

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

Если одно и то же свойство определено как системное свойство и в файле свойств, то будет применено системное свойство.

Предположим, у нас есть приоритет свойства, определенный как системное свойство со значением свойства System и определенный как что-то еще в файле свойств. Значение будет системным свойством :

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

Иногда нам нужно ввести кучу значений. Было бы удобно определить их как разделенные запятыми значения для одного свойства в файле свойств или как системное свойство и внедрить в массив.

В первом разделе мы определили значения, разделенные запятыми, в listOfValues файла свойств , поэтому значения массива будут ["A", "B", "C"]:

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

4. Продвинутые примеры с SpEL

Мы также можем использовать выражения SpEL для получения значения.

Если у нас есть системное свойство с именем priority, то его значение будет применено к полю:

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

Если мы не определили системное свойство, то будет присвоено нулевое значение.

Чтобы предотвратить это, мы можем указать значение по умолчанию в выражении SpEL. Мы получаем какое-то значение по умолчанию для поля, если системное свойство не определено:

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

Кроме того, мы можем использовать значение поля из других компонентов. Предположим, у нас есть bean-компонент с именем someBean с полем someValue, равным 10 . Тогда 10 будет присвоено полю:

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

Мы можем манипулировать свойствами, чтобы получить список значений, здесь список строковых значений A, B и C:

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

5. Использование @Value с картами

Мы также можем использовать аннотацию @Value для внедрения свойства Map .

Во-первых, нам нужно определить свойство в форме {key: 'value' } в нашем файле свойств:

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

Обратите внимание, что значения на карте должны быть заключены в одинарные кавычки.

Теперь мы можем внедрить это значение из файла свойств как Map :

@Value("#{${valuesMap}}")
private Map<String, Integer> valuesMap;

Если нам нужно получить значение определенного ключа в Map , все, что нам нужно сделать, это добавить имя ключа в выражение :

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

Если мы не уверены, содержит ли Map определенный ключ, мы должны выбрать более безопасное выражение, которое не будет генерировать исключение, а установит значение null , если ключ не найден:

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

Мы также можем установить значения по умолчанию для свойств или ключей, которые могут не существовать :

@Value("#{${unknownMap : {key1: '1', key2: '2'}}}")
private Map<String, Integer> unknownMap;

@Value("#{${valuesMap}['unknownKey'] ?: 5}")
private Integer unknownMapKeyWithDefaultValue;

Записи карты также могут быть отфильтрованы перед внедрением.

Предположим, нам нужно получить только те записи, значения которых больше единицы:

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

Мы также можем использовать аннотацию @Value для внедрения всех текущих свойств системы :

@Value("#{systemProperties}")
private Map<String, String> systemPropertiesMap;

6. Использование @Value с внедрением конструктора

Когда мы используем аннотацию @Value , мы не ограничиваемся внедрением поля. Мы также можем использовать его вместе с внедрением конструктора.

Давайте посмотрим это на практике:

@Component
@PropertySource("classpath:values.properties")
public class PriorityProvider {

private String priority;

@Autowired
public PriorityProvider(@Value("${priority:normal}") String priority) {
this.priority = priority;
}

// standard getter
}

В приведенном выше примере мы вводим приоритет непосредственно в наш конструктор PriorityProvider .

Обратите внимание, что мы также предоставляем значение по умолчанию на случай, если свойство не будет найдено.

7. Использование @Value с внедрением сеттера

По аналогии с внедрением конструктора мы также можем использовать @Value с внедрением сеттера.

Давайте взглянем:

@Component
@PropertySource("classpath:values.properties")
public class CollectionProvider {

private List<String> values = new ArrayList<>();

@Autowired
public void setValues(@Value("#{'${listOfValues}'.split(',')}") List<String> values) {
this.values.addAll(values);
}

// standard getter
}

Мы используем выражение SpEL для ввода списка значений в метод setValues .

8. Заключение

В этой статье мы рассмотрели различные возможности использования аннотации @Value с простыми свойствами, определенными в файле, с системными свойствами и со свойствами, вычисляемыми с помощью выражений SpEL.

Как всегда, пример приложения доступен на проекте GitHub .