Spring: @Value aннотация
Основная цель этой статьи - помочь вам понять, как работает аннотация Spring @Value.
@Value
является аннотацией Java, которая используется на уровне параметра поля или метода / конструктора и указывает значение по умолчанию для затронутого аргумента. Он обычно используется для ввода значений в конфигурационные переменные - что мы покажем и объясним в следующей части статьи.
Основное назначение
Для самых простых примеров мы назначим значения трем различным полям, используя аннотацию @Value
, дав им явные значения:
@Value("John")
private String trainee;
@Value("100")
private int hoursOfCode;
@Value("true")
private boolean passedAssesmentTest;
Очень важно отметить, что аргумент, переданный аннотации @Value
, может быть только String
. Spring преобразует значение в указанный тип, и присвоение будет выполнено без проблем, даже если мы передаем переменным String
значение int
или boolean
.
Spring Environment
Внедрение значений из файлов свойств с помощью аннотации @Value
, вероятно, наиболее часто используется в реальных приложениях.
Мы будем использовать файл свойств по умолчанию для Spring Boot - application.properties
, где мы можем определить переменные, к которым мы сможем обращаться позже:
car.brand=Audi
car.color=Red
car.power=150
@Value("${car.brand")
private String brand;
@Value("${car.color}")
private String color;
@Value("${car.power}")
private int power;
В этом примере значения переменных считываются из файла application.properties
и присваиваются им во время создания компонента.
В большинстве случаев мы использовали бы этот подход для вставки значений конфигурации из файла application.properties
в bean-компоненты.
Значение по умолчанию
Значения по умолчанию используются как «запасной вариант», если свойство, которое мы хотим внедрить, не определено или отсутствует:
@Value("${car.type:Sedan}")
private String type;
В приведенном выше примере, потому как мы не имеем никакого значения car.type
в application.properties
, Spring присвоит Sedan
к переменной type
в качестве значения по умолчанию.
Если свойство car.type
вставляется в файл свойств, вместо него будет использоваться новое значение.
Системные переменные
Мы также можем получить доступ к системным переменным, которые хранятся в виде свойств приложения Spring при запуске:
@Value("${user.name}")
// Or
@Value("${username}")
private String userName;
@Value("${number.of.processors}")
// Or
@Value("${number_of_processors}")
private int numberOfProcessors;
@Value("${java.home}")
private String java;
Переменные могут вызываться с различными соглашениями об именах - Spring ищет нас и присваивает правильное значение.
Значение глобального метода
Поскольку @Value
обрабатывается классом BeanPostProcessor
, он будет вызываться, когда Spring создает контекст Spring, создавая экземпляры файлов конфигурации и компонентов.
Это означает, что при наличии метода @Value
все аргументы будут сопоставлены со значением, указанным в аннотации:
@Value("${car.brand}")
public CarData setCarData(String color, String brand) {
carData.setCarColor(color);
carData.setCarBrand(brand);
}
Если мы печатаем, carData.getCarColor()
и carData.getCarBrand()
мы получим значение car.brand
оба раза, потому что, как мы сказали, все аргументы будут сопоставлены с предоставленным значением.
Параметр метода Value
Мы можем исправить это, используя @Value
непосредственно с параметр метода:
@Value("${car.brand}")
public CarData setCarData(@Value("${car.color}") String color, String brand) {
carData.setCarColor(color);
carData.setCarBrand(brand);
}
Теперь, если мы печатаем значения из объекта carData
- поле цвета будет иметь значение car.color
, потому что мы предоставили значение для параметра самого метода.
Spring Expression Language (SpEL)
Язык выражений Spring (SpEL) - это язык выражений, который служит основой для оценки выражений в портфолио Spring.
По сути, когда мы используем SpEL вместе с аннотацией @Value
, мы просто меняем способ сказать Spring, что нам нужно. Давайте внимательнее посмотрим:
@Value("#{systemProperties['user.name']}")
private String userName;
Это то, как вы вводите конкретное системное свойство. С другой стороны, мы можем добавить все свойства:
@Value("#{systemProperties}")
private Map properties;
Теперь мы знаем, что мы можем использовать аннотацию @Value
для методов как глобальное значение или как значение параметра.
Поскольку конструкторы по сути являются методами, мы можем использовать аннотацию и в конструкторах:
public Driver(@Value("#{systemProperties['user.name']}") String name, String location) {
this.name = name;
this.location = location;
}
Инъекция в Map
С SpEL мы можем сделать некоторые другие довольно интересные вещи в сочетании с аннотацией @Value
. Например, давайте сделаем Map, представляет что indoor
и outdoor
хобби студента. Каждый из них может иметь несколько значений:
student.hobbies={indoor: 'reading, drawing', outdoor: 'fishing, hiking, bushcraft'}
Теперь, чтобы ввести это, нам понадобится Map
:
@Value("#{${student.hobbies}}")
private Map> hobbies;
Внедрение в списки
Если свойство имеет значения, разделенные запятыми, например, простой список книг, мы можем использовать SpEL для его интерпретации и преобразования в список:
student.booksRead=Harry Potter,The Hobbit,Game of Thrones
Используя метод split()
и разделяя для каждой запятой (,
), мы можем вставить эти значения в список:
@Value("#{'${student.booksRead}'.split(',')}")
private List booksRead;
Вывод
Как только вы заканчиваете работу над реальным приложением, вы понимаете, что конфигурация является важной темой, и если вы используете Spring. Существует большая вероятность того, что вы уже используете или вам придется широко использовать аннотацию @Value
.
Понимание этой базовой функциональности очень важно, потому что если вы этого не сделаете, вы можете использовать ее совершенно неправильно.