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

Пружинные профили

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

1. Обзор

В этом уроке мы сосредоточимся на представлении профилей в Spring.

Профили — это основная функция фреймворка , позволяющая нам сопоставлять наши bean-компоненты с разными профилями — например, dev , test и prod .

Затем мы можем активировать разные профили в разных средах, чтобы загружать только те bean-компоненты, которые нам нужны.

2. Используйте @Profile на бине

Давайте начнем с простого и посмотрим, как мы можем сделать bean-компонент принадлежащим определенному профилю. Мы используем аннотацию @Profile — мы сопоставляем компонент с этим конкретным профилем ; аннотация просто берет имена одного (или нескольких) профилей.

Рассмотрим базовый сценарий: у нас есть bean-компонент, который должен быть активен только во время разработки, но не должен быть развернут в рабочей среде.

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

@Component
@Profile("dev")
public class DevDatasourceConfig

В качестве краткого примечания: имена профилей также могут иметь префикс оператора НЕ, например, !dev , чтобы исключить их из профиля.

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

@Component
@Profile("!dev")
public class DevDatasourceConfig

3. Объявить профили в XML

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

<beans profile="dev">
<bean id="devDatasourceConfig"
class="org.foreach.profiles.DevDatasourceConfig" />
</beans>

4. Установите профили

Следующим шагом является активация и настройка профилей, чтобы соответствующие компоненты были зарегистрированы в контейнере.

Это можно сделать различными способами, которые мы рассмотрим в следующих разделах.

4.1. Программно через интерфейс WebApplicationInitializer

В веб-приложениях WebApplicationInitializer можно использовать для программной настройки ServletContext .

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

@Configuration
public class MyWebApplicationInitializer
implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

servletContext.setInitParameter(
"spring.profiles.active", "dev");
}
}

4.2. Программно через ConfigurableEnvironment

Мы также можем установить профили непосредственно в среде:

@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");

4.3. Параметр контекста в web.xml

Точно так же мы можем определить активные профили в файле web.xml веб-приложения, используя параметр контекста:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>

4.4. Системный параметр JVM

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

-Dspring.profiles.active=dev

4.5. Переменная среды

В среде Unix профили также можно активировать с помощью переменной среды :

export spring_profiles_active=dev

4.6. Профиль Мейвена

Профили Spring также можно активировать через профили Maven, указав свойство конфигурации spring.profiles.active .

В каждом профиле Maven мы можем установить свойство spring.profiles.active :

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>

Его значение будет использоваться для замены заполнителя @ spring.profiles.active@ в application.properties :

spring.profiles.active=@spring.profiles.active@

Теперь нам нужно включить фильтрацию ресурсов в pom.xml :

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>

и добавьте параметр -P , чтобы переключить, какой профиль Maven будет применяться:

mvn clean package -Pprod

Эта команда упакует приложение для профиля prod . Он также применяет значение prod spring.profiles.active для этого приложения, когда оно работает. ``

4.7. @ActiveProfile в тестах

Тесты позволяют очень легко указать, какие профили активны, используя аннотацию @ActiveProfile для включения определенных профилей:

@ActiveProfiles("dev")

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

  1. Параметр контекста в web.xml
  2. Инициализатор веб-приложений
  3. Системный параметр JVM
  4. Переменная среды
  5. Профиль Мейвена

5. Профиль по умолчанию

Любой bean-компонент, для которого не указан профиль, принадлежит профилю по умолчанию .

Spring также предоставляет способ установить профиль по умолчанию, когда никакой другой профиль не активен — с помощью свойства spring.profiles.default .

6. Получите активные профили

Активные профили Spring управляют поведением аннотации @Profile для включения/отключения bean-компонентов. Однако мы также можем захотеть получить доступ к списку активных профилей программно.

У нас есть два способа сделать это, используя Environment или spring.active.profile .

6.1. Использование среды

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

public class ProfileManager {
@Autowired
   private Environment environment;

    public void getActiveProfiles() {
        for (String profileName : environment.getActiveProfiles()) {
            System.out.println("Currently active profile - " + profileName);
        }  
    }
}

6.2. Использование spring.active.profile

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

@Value("${spring.profiles.active}")
private String activeProfile;

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

Однако мы должны подумать, что произойдет, если активного профиля вообще не будет. В приведенном выше коде отсутствие активного профиля предотвратило бы создание контекста приложения. Это приведет к исключению IllegalArgumentException из-за отсутствия заполнителя для внедрения в переменную.

Чтобы избежать этого, мы можем определить значение по умолчанию :

@Value("${spring.profiles.active:}")
private String activeProfile;

Теперь, если нет активных профилей, наш активный профиль будет содержать пустую строку.

И если мы хотим получить доступ к их списку, как в предыдущем примере, мы можем сделать это, разделив переменную activeProfile :

public class ProfileManager {
@Value("${spring.profiles.active:}")
private String activeProfiles;

public String getActiveProfiles() {
for (String profileName : activeProfiles.split(",")) {
System.out.println("Currently active profile - " + profileName);
}
}
}

7. Пример: отдельные конфигурации источников данных с использованием профилей

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

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

Давайте создадим общий интерфейс DatasourceConfig , который должен быть реализован обеими реализациями источника данных:

public interface DatasourceConfig {
public void setup();
}

Ниже приведена конфигурация среды разработки:

@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for DEV environment. ");
}
}

И конфигурация для производственной среды:

@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for PRODUCTION environment. ");
}
}

Теперь давайте создадим тест и внедрим наш интерфейс DatasourceConfig; в зависимости от активного профиля Spring внедрит bean-компонент DevDatasourceConfig или ProductionDatasourceConfig :

public class SpringProfilesWithMavenPropertiesIntegrationTest {
@Autowired
DatasourceConfig datasourceConfig;

public void setupDatasource() {
datasourceConfig.setup();
}
}

Когда профиль разработчика активен, Spring вводит объект DevDatasourceConfig , и при вызове метода setup() выводится следующее:

Setting up datasource for DEV environment.

8. Профили в Spring Boot

Spring Boot поддерживает все конфигурации профилей, описанные до сих пор, с несколькими дополнительными функциями.

8.1. Активация или настройка профиля

Параметр инициализации spring.profiles.active , представленный в разделе 4, также можно настроить как свойство в Spring Boot для определения текущих активных профилей. Это стандартное свойство, которое Spring Boot подберет автоматически:

spring.profiles.active=dev

Однако, начиная с Spring Boot 2.4, это свойство нельзя использовать в сочетании с spring.config.activate.on-profile , так как это может вызвать исключение ConfigDataException ( т . е . InvalidConfigDataPropertyException или InactiveConfigDataAccessException ).

Для программной установки профилей мы также можем использовать класс SpringApplication :

SpringApplication.setAdditionalProfiles("dev");

Чтобы установить профили с помощью Maven в Spring Boot, мы можем указать имена профилей в spring-boot-maven-plugin в pom.xm l :

<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>dev</profile>
</profiles>
</configuration>
</plugin>
...
</plugins>

и выполните цель Maven, специфичную для Spring Boot:

mvn spring-boot:run

8.2. Файлы свойств для конкретных профилей

Однако самая важная функция Spring Boot, связанная с профилями, — это файлы свойств для конкретных профилей. Они должны быть названы в формате application-{profile}.properties .

Spring Boot автоматически загрузит свойства в файле application.properties для всех профилей, а свойства в файлах .properties для конкретных профилей — только для указанного профиля.

Например, мы можем настроить разные источники данных для профилей разработки и производства , используя два файла с именами application-dev.properties и application-production.properties :

В файле application-production.properties мы можем настроить источник данных MySql :

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root

Затем мы можем настроить те же свойства для профиля dev в файле application-dev.properties , чтобы использовать базу данных H2 в памяти :

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

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

До Spring Boot 2.4 можно было активировать профиль из документов по конкретному профилю. Но это уже не так; в более поздних версиях инфраструктура снова выдаст InvalidConfigDataPropertyException или InactiveConfigDataAccessException в этих обстоятельствах.

8.3. Файлы с несколькими документами

Чтобы еще больше упростить определение свойств для отдельных сред, мы можем даже объединить все свойства в одном файле и использовать разделитель для обозначения профиля.

Начиная с версии 2.4, Spring Boot расширил поддержку многодокументных файлов для файлов свойств в дополнение к ранее поддерживаемому YAML . Итак, теперь мы можем указать свойства разработки и производства в одном и том же application.properties :

my.prop=used-always-in-all-profiles
#---
spring.config.activate.on-profile=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
#---
spring.config.activate.on-profile=production
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

Этот файл читается Spring Boot сверху вниз. То есть, если какое-то свойство, скажем, my.prop , еще раз встречается в конце в приведенном выше примере, будет рассматриваться самое конечное значение.

8.4. Группы профилей

Еще одна функция, добавленная в Boot 2.4, — группы профилей. Как следует из названия, это позволяет нам группировать похожие профили вместе .

Давайте рассмотрим вариант использования, в котором у нас будет несколько профилей конфигурации для производственной среды. Скажем, proddb для базы данных и prodquartz для планировщика в производственной среде.

Чтобы включить эти профили сразу через наш файл application.properties , мы можем указать:

spring.profiles.group.production=proddb,prodquartz

Следовательно, активация производственного профиля также активирует proddb и prodquartz .

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

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

Наконец, мы подтвердили наше понимание профилей на простом, но реальном примере.

Реализацию этого туториала можно найти в проекте GitHub .