Статьи

Поддержка заполнителей в аннотациях Value в Spring

${...} заполнители в аннотации @Value используются для доступа к свойствам, зарегистрированным в @PropertySource . Это чрезвычайно полезно с @Configuration компонентами @Configuration в приложениях Spring, но не только. Чтобы убедиться, что это возможно, PropertySourcesPlaceholderConfigurer должен присутствовать во всех контекстах приложения, для которых требуется разрешение заполнителей.

В этом посте вы узнаете, как настроить разрешение заполнителей в приложениях Spring 4 и внедрить различные типы объектов с @Value аннотации @Value , включая JSR-310 Date-Time, JSR-354 Money & Currency или java.util.Optional .

Регистрация PropertySourcesPlaceholderConfigurer

В приложениях Spring с конфигурацией no-xml статический компонент PropertySourcesPlaceholderConfigurer должен быть зарегистрирован во всех контекстах приложения.

Чтобы зарегистрировать PropertySourcesPlaceholderConfigurer просто добавьте статический бин того же типа в конфигурацию вместе с источниками свойств, к которым вы хотите иметь доступ. Для импорта нескольких источников свойств используйте аннотацию @PropertySources (до Java 8) или несколько аннотаций @PropertySource (Java 8).

01
02
03
04
05
06
07
08
09
10
11
@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan
class ApplicationConfig {
 
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
 
}

Другой способ добавить источник свойства в конфигуратор — вызвать его метод setLocation :

01
02
03
04
05
06
07
08
09
10
11
12
@Configuration
@ComponentScan
class ApplicationConfig {
 
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
        c.setLocation(new ClassPathResource("application.properties"));
        return c;
    }
 
}

Внедрение простых свойств

Теперь вы можете легко получить доступ к свойствам с @Value аннотации @Value и заполнителей:

1
2
3
4
5
6
@Value("${my.string.property}")
private String stringProperty;
@Value("${my.int.property}")
private int intProperty;
@Value("${my.boolean.property}")
private boolean boolProperty;

Свойства определены в файле application.properties :

1
2
3
my.string.property=Some text
my.int.property=42
my.boolean.property=true

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

1
java.lang.IllegalArgumentException: Could not resolve placeholder 'placeholder' in string value "${placeholder}"

Игнорирование неразрешимых заполнителей

Если вы хотите автоматически игнорировать все неразрешимые заполнители, установите соответствующий флаг конфигуратора:

1
2
3
PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
 
c.setIgnoreUnresolvablePlaceholders(true);

Значения по умолчанию

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

1
2
@Value("${my.string.property:Sample}")
private String stringProperty;

Также поддерживается пустое значение по умолчанию, что приводит к пустой stringProperty :

1
2
@Value("${my.string.property:}")
private String stringProperty;

Нулевые значения

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

1
2
PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
c.setNullValue("");

Это может быть полезно, особенно когда я работаю с java.util.Optional (см. Ниже).

Внедрение непростых свойств

Чтобы внедрить сложные свойства с @Value аннотации @Value , необходимо сделать доступным Spring ConversionService в контексте приложения. Регистрация сервиса конвертации по умолчанию дает возможность вводить списки, массивы и другие конвертируемые типы. Обычно, в контексте сервлета Spring, ConversionService будет зарегистрирован (например, через @EnableWebMvc ), но для ручной регистрации вы можете использовать следующий код. Обратите внимание, что имя bean-компонента должно быть conversionService :

1
2
3
4
@Bean
public static ConversionService conversionService() {
    return new DefaultFormattingConversionService();
}

DefaultFormattingConversionService поддерживает все распространенные конвертеры и форматеры, включая форматеры для JSR-354 Money & Currency, JSR-310 Date-Time и / или Joda-Time.

Инъекционный список / массивы

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

1
2
my.intList.property=1,2,3,4,5
my.stringArray.property=1,2,3,4,5

И вводить их так:

1
2
3
4
5
@Value("${my.intList.property}")
private List<Integer> intList;
 
@Value("${my.stringArray.property}")
private List<Integer> stringArray;

Инъекция java.util.Optional

Дополнительный Java 8 дает прекрасную возможность работать с дополнительными свойствами. Хитрость с внедрением Optional с @Value заключается в том, что значения свойств должны быть проанализированы с null значением, и для достижения этого свойства nullValue в конфигураторе должно быть установлено соответственно (как показано ранее).

1
2
@Value("${my.optional.property:}")
private Optional<String> optional;

Если свойство my.optional.property , optional будет содержать Optional.empty и поэтому его можно использовать в коде:

1
2
3
if (optional.isPresent()) {
    // do something cool
}

Внедрение типов java.time

Зарегистрированные ConversionService содержит форматеры для даты и времени JSR-310. Ниже приведены примеры для LocalDate и LocalDateTime в текущей локали:

1
2
3
# format for en_US locale
my.localDate.property=9/28/15
my.localDateTime.property=9/28/15 10:05 PM
1
2
3
4
@Value("${my.localDate.property}")
private LocalDate localDate;
@Value("${my.localDateTime.property}")
private LocalDateTime localDateTime;

Внедрение javax.money типов

Как только javax.money окажется на пути к классам, вы можете ввести MonetaryAmount и CurrencyUnit :

1
2
my.monetaryAmount.property=USD 299
my.currencyUnit.property=USD
1
2
3
4
@Value("${my.monetaryAmount.property}")
private MonetaryAmount monetaryAmount;
@Value("${my.currencyUnit.property}")
private CurrencyUnit currencyUnit;

Внедрение пользовательских типов

С ConversionService относительно легко зарегистрировать пользовательские конвертеры. В приведенном ниже примере объект java.util.Pattern будет создан из строкового значения: my.pattern.property=[0-9].* . Для этого нам нужно добавить пользовательский конвертированный:

1
2
3
DefaultFormattingConversionService cs = new DefaultFormattingConversionService();
 
cs.addConverter(String.class, Pattern.class, (Converter<String, Pattern>) Pattern::compile);

Теперь свойство может быть введено, как показано ниже:

1
2
@Value("${my.pattern.property}")
private Pattern pattern;

Дополнительно — доступ к свойствам Spring в представлении Thymeleaf

Если вы работаете с Thymeleaf и хотите получить доступ к свойствам, зарегистрированным в среде Spring (с PropertySourcesPlaceholderConfigurer или просто с @PropertySource ), вы можете использовать способность Thymeleaf для доступа к свойствам Spring Beans с использованием синтаксиса SpringEL: $ {@ myBean.doSomething ()}. Все свойства доступны через интерфейс Environment , поэтому получить доступ к нему в Thymeleaf так же просто, как вызвать его метод getProperty :

1
2
3
<div th:fragment="footer" th:align="center">
    <span th:text="${@environment.getProperty('app.version')}"></span>
 </div>

Закрытие заметки

Вы можете найти простое использование аннотации @Value и PropertySourcesPlaceholderConfigurer в @Value моего Spring-архетипа здесь: https://github.com/kolorobot/spring-mvc-quickstart-archetype .

Если вы работаете с Spring Boot, вы можете прочитать о свойствах безопасной конфигурации типов: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config- типизированная-конфигурация-свойство