Свойства с Spring и Spring Boot

Свойства с Spring и Spring Boot

1. обзор

В этом руководстве будет показано, как настроить и использоватьProperties in Spring - через конфигурацию Java и@PropertySource или через XML и<property-placeholder>,as well how properties work in Spring Boot..

Дальнейшее чтение:

Руководство по языку Spring Expression

В этой статье рассматривается язык выражений Spring (SpEL), мощный язык выражений, который поддерживает запросы и манипуляции с объектными графами во время выполнения.

Read more

Настройте веб-приложение Spring Boot

Некоторые из наиболее полезных конфигов для приложения Spring Boot.

Read more

Руководство по @ConfigurationProperties в Spring Boot

Краткое и практическое руководство по аннотации @ConfigurationProperties в Spring Boot.

Read more

2. Зарегистрируйте файл свойств с помощью аннотаций Java

Spring 3.1 также представляетthe new @PropertySource annotation как удобный механизм для добавления источников свойств в среду. Эта аннотация должна использоваться вместе с конфигурацией на основе Java и аннотацией@Configuration:

@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
    //...
}

Еще один очень полезный способ регистрации нового файла свойств - использовать заполнитель, позволяющий вамdynamically select the right file at runtime; Например:

@PropertySource({
  "classpath:persistence-${envTarget:mysql}.properties"
})
...

2.1. Определение нескольких местоположений свойств

Аннотация@PropertySource повторяетсяaccording to Java 8 conventions. Поэтому, если мы используем Java 8 или выше, мы можем использовать эту аннотацию для определения нескольких местоположений свойств:

@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
    //...
}

Конечно, мы также можем использовать аннотацию@PropertySources и указать массив@PropertySource. Это работает в любой поддерживаемой версии Java, а не только в Java 8 или выше:

@PropertySources({
    @PropertySource("classpath:foo.properties"),
    @PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
    //...
}

В любом случае стоит отметить, чтоin the event of a property name collision, the last source read takes precedence.

3. Зарегистрируйте файл свойств в XML

В XML новые файлы свойств можно сделать доступными для Spring черезthe <context:property-placeholder … > namespace element:

Файлfoo.properties следует разместить в папке/src/main/resources, чтобы он был доступен в пути к классам во время выполнения.

В случае, еслиmultiple <property-placeholder> elements присутствует в контексте Spring, есть несколько рекомендуемых передовых практик:

  • атрибутorder необходимо указать, чтобы исправить порядок, в котором они обрабатываются Spring

  • все заполнители свойств за вычетом последнего (наивысшийorder) должны иметьignore-unresolvable=”true”, чтобы механизм разрешения передавался другим в контексте, не вызывая исключения

3.1. Зарегистрируйте несколько файлов свойств в XML

В предыдущем разделе мы увидели, как определить несколько файлов свойств, используя аннотации в Java 8 или более поздней версии. Аналогично мы можемdefine multiple properties files using XML configuration:

И, как и раньше,in the event of a property name collision, the last source read takes precedence.

4. Использование / внедрение свойств

Injecting a property with the @Value annotation прост:

@Value( "${jdbc.url}" )
private String jdbcUrl;

A default value of the property также можно указать:

@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;

Использование свойств в конфигурации Spring XML:


  

И старыйPropertyPlaceholderConfigurer, и новыйPropertySourcesPlaceholderConfigurer добавлены в Spring 3.1resolve $\{…} placeholders в значениях свойств определения bean-компонентов и аннотациях@Value.

Наконец, мы можем obtain the value of a property using the Environment API:

@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));

Здесь очень важное предостережение:using <property-placeholder> will not expose the properties to the Spring Environment - это означает, что получение такого значения не будет работать - оно вернетnull:

env.getProperty("key.something")

5. Свойства с Spring Boot

Прежде чем перейти к более сложным параметрам конфигурации свойств, давайте посмотрим наthe new properties support in Spring Boot.

Вообще говоря, эта новая поддержка включаетless configuration по сравнению со стандартным Spring, что, конечно же, является одной из основных целей Boot.

5.1. application.properties - файл свойств по умолчанию

Boot применяет свое типичное соглашение о подходе к настройке файлов свойств. Это означает, что мы можем просто поместить файл «application.properties» в наш каталог «src/main/resources», и он будет обнаружен автоматически. Затем мы можем добавить любые загруженные свойства из него как обычно.

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

При необходимости мы также можем настроить другой файл во время выполнения, используя свойство среды:

java -jar app.jar --spring.config.location=classpath:/another-location.properties

5.2. Файл специфических свойств среды

Если нам нужно настроить таргетинг на разные среды, в Boot есть встроенный механизм.

Мы можем просто определить файл“application-environment.properties” в каталоге“src/main/resources”, а затем установить профиль Spring с тем же именем среды.

Например, если мы определяем «промежуточную» среду, это означает, что нам нужно будет определить профильstaging, а затемapplication-staging.properties.

Этот файл env будет загружен иwill take precedence over the default property file. Обратите внимание, что файл по умолчанию все равно будет загружен, просто при конфликте свойств приоритет имеет файл свойств конкретной среды.

5.3. Файл специальных свойств теста

У нас также может быть требование использовать разные значения свойств во время тестирования нашего приложения.

Spring Boot справляется с этим за нас, заглядывая в каталог «src/test/resources» во время тестового запуска. Опять же, свойства по умолчанию все еще будут вводиться как обычно, но будут переопределены, если есть столкновение.

5.4. Аннотация@TestPropertySource

Если нам нужен более детальный контроль над тестовыми свойствами, мы можем использовать аннотацию@TestPropertySource.

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

@ContextConfiguration
@TestPropertySource("/my-test.properties")
public class IntegrationTests {
    // tests
}

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

@ContextConfiguration
@TestPropertySource("foo=bar", "bar=foo")
public class IntegrationTests {
    // tests
}

Мы также можем добиться аналогичного эффекта, используя аргументproperties аннотации@SpringBootTest:

@SpringBootTest(properties = {"foo=bar", "bar=foo"})
public class IntegrationTests {
    // tests
}

5.5. Иерархические свойства

Если у нас есть свойства, которые сгруппированы вместе, мы можем использовать аннотацию@ConfigurationProperties, которая будет отображать эти иерархии свойств в графы объектов Java.

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

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar

А затем давайте воспользуемся аннотацией, чтобы сопоставить их с объектом базы данных:

@ConfigurationProperties(prefix = "database")
public class Database {
    String url;
    String username;
    String password;

    // standard getters and setters
}

Spring Boot снова применяет свое соглашение к конфигурации, автоматически сопоставляя имена свойств и их соответствующие поля. Все, что нам нужно предоставить, это префикс свойства.

Если вы хотите глубже изучить свойства конфигурации, взгляните наthe in-depth article.

5.6. Альтернатива - файлы YAML

YAML файлы также поддерживаются.

Все те же правила именования применяются к тестовым файлам, файлам среды и файлам свойств по умолчанию. Единственное отличие - это расширение файла и зависимость от библиотекиSnakeYAML в вашем пути к классам.

YAML особенно хорош для хранения иерархических свойств; следующий файл свойств:

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
secret: foo

Синонимичен следующему файлу YAML:

database:
  url: jdbc:postgresql:/localhost:5432/instance
  username: foo
  password: bar
secret: foo

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

5.7. Свойства из аргументов командной строки

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

java -jar app.jar --property="value"

Вы также можете сделать это через системные свойства, которые предоставляются перед командой-jar, а не после нее:

java -Dproperty.name="value" -jar app.jar

5.8. Свойства из переменных среды

Spring Boot также определяет переменные среды, обрабатывая их как свойства:

export name=value
java -jar app.jar

5.9 Randomization of Property Values

Если нам не нужны детерминированные значения свойств, можно использоватьRandomValuePropertySource для рандомизации значений свойств:

random.number=${random.int}
random.long=${random.long}
random.uuid=${random.uuid}

5.10. Дополнительные типы источников собственности

Spring Boot поддерживает множество источников свойств, реализуя продуманное упорядочение для обеспечения разумного переопределения. Стоит проконсультироваться сofficial documentation, который выходит за рамки данной статьи.

6. Конфигурация с использованием Raw Beans в Spring 3.0 -PropertyPlaceholderConfigurer

Помимо удобных методов получения свойств в Spring - аннотаций и пространства имен XML - компонент конфигурации свойств также может быть определен и зарегистрированmanually. Работа сPropertyPlaceholderConfigurer дает нам полный контроль над конфигурацией, но с другой стороны, это более подробный и ненужный большую часть времени.

6.1. Конфигурация Java

@Bean
public static PropertyPlaceholderConfigurer properties() {
    PropertyPlaceholderConfigurer ppc
      = new PropertyPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[]
      { new ClassPathResource( "foo.properties" ) };
    ppc.setLocations( resources );
    ppc.setIgnoreUnresolvablePlaceholders( true );
    return ppc;
}

6.2. Конфигурация XML


    
        
            classpath:foo.properties
        
    
    

7. Конфигурация с использованием Raw Beans в Spring 3.1 -PropertySourcesPlaceholderConfigurer

Точно так же в Spring 3.1 новыйPropertySourcesPlaceholderConfigurer также можно настроить вручную:

7.1. Конфигурация Java

@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
    PropertySourcesPlaceholderConfigurer pspc
      = new PropertySourcesPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[ ]
      { new ClassPathResource( "foo.properties" ) };
    pspc.setLocations( resources );
    pspc.setIgnoreUnresolvablePlaceholders( true );
    return pspc;
}

7.2. Конфигурация XML


    
        
            classpath:foo.properties
        
    
    

8. Свойства в родительско-дочерних контекстах

Этот вопрос возникает снова и снова - что произойдет, когда вашweb application has a parent and a child context? Родительский контекст может иметь некоторую общую функциональность ядра и bean-компоненты, а затем один (или несколько) дочерних контекстов, возможно, содержащих специфичные для сервлета bean-компоненты.

В таком случае, как лучше всего определять файлы свойств и включать их в эти контексты? Более того - как лучше всего получить эти свойства из Spring? Вот простая разбивка.

8.1. Если файл свойств определен в XML с помощью roperty-placeholder>

Если файлdefined in the Parent context:

  • @Value работает вChild context: НЕТ

  • @Value работает вParent context: ДА

Если файлdefined in the Child context:

  • @Value работает вChild context: ДА

  • @Value работает вParent context: НЕТ

Наконец, как мы обсуждали ранее,<property-placeholder> не раскрывает свойства окружающей среде, поэтому:

  • environment.getProperty работает вeither context: НЕТ

8.2. Если файл свойств определен в Java с помощью@PropertySource

Если файлdefined in the Parent context:

  • @Value работает вChild context: ДА

  • @Value работает вParent context: ДА

  • environment.getProperty вChild context: ДА

  • environment.getProperty вParent context: ДА

Если файлdefined in the Child context:

  • @Value работает вChild context: ДА

  • @Value работает вParent context: НЕТ

  • environment.getProperty вChild context: ДА

  • environment.getProperty вParent context: НЕТ

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

В этой статье показано несколькоexamples of working with properties and properties files in Spring.

Как всегда, доступен весь код статьиover on Github. Это проект, основанный на Maven, поэтому его легко импортировать и запускать как есть.