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

Аннотация Spring @ConditionalOnProperty

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

1. Обзор

В этом коротком руководстве мы рассмотрим основное назначение аннотации @ConditionalOnProperty .

Во-первых, мы начнем с небольшого предыстории того, что такое @ConditionalOnProperty . Затем мы рассмотрим несколько практических примеров, которые помогут понять, как это работает и какие возможности предоставляет.

2. Назначение @ConditionalOnProperty

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

Например, мы можем захотеть зарегистрировать bean-компонент DataSource , чтобы он указывал на производственную или тестовую базу данных, в зависимости от того, устанавливаем ли мы значение свойства «prod» или «test».

К счастью, добиться этого не так сложно, как может показаться на первый взгляд. Фреймворк Spring предоставляет аннотацию @ConditionalOnProperty именно для этой цели.

Короче говоря, @ConditionalOnProperty разрешает регистрацию компонента только в том случае, если свойство среды присутствует и имеет определенное значение. По умолчанию указанное свойство должно быть определено и не равно false .

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

3. Аннотация @ConditionalOnProperty на практике

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

Во-первых, нам нужно создать простую службу для отправки уведомления. Например, рассмотрим интерфейс NotificationSender :

public interface NotificationSender {
String send(String message);
}

Далее давайте обеспечим реализацию интерфейса NotificationSender для отправки наших электронных писем:

public class EmailNotification implements NotificationSender {
@Override
public String send(String message) {
return "Email Notification: " + message;
}
}

Теперь давайте посмотрим, как использовать аннотацию @ConditionalOnProperty . Давайте настроим bean- компонент NotificationSender таким образом, чтобы он загружался только в том случае, если определено свойство notification.service :

@Bean(name = "emailNotification")
@ConditionalOnProperty(prefix = "notification", name = "service")
public NotificationSender notificationSender() {
return new EmailNotification();
}

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

Наконец, нам нужно добавить последнюю часть головоломки. Давайте определим наше пользовательское свойство в файле application.properties :

notification.service=email

4. Расширенная конфигурация

Как мы уже узнали, аннотация @ConditionalOnProperty позволяет нам регистрировать bean-компоненты условно в зависимости от наличия свойства конфигурации.

Однако с помощью этой аннотации мы можем сделать больше . Итак, давайте исследовать!

Предположим, мы хотим добавить еще одну службу уведомлений, например службу, которая позволит нам отправлять SMS-уведомления.

Для этого нам нужно создать еще одну реализацию NotificationSender :

public class SmsNotification implements NotificationSender {
@Override
public String send(String message) {
return "SMS Notification: " + message;
}
}

Поскольку у нас есть две реализации, давайте посмотрим, как мы можем использовать @ConditionalOnProperty для условной загрузки правильного bean -компонента NotificationSender .

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

Теперь укажем, при каком условии мы хотим зарегистрировать реализацию SmsNotification в контексте:

@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
return new SmsNotification();
}

С помощью атрибутаhavingValue мы дали понять, что хотим загружать SmsNotification только тогда , когда дляnotification.serviceустановлено значение sms .

Стоит отметить, что @ConditionalOnProperty имеет еще один атрибут, называемый matchIfMissing . Этот атрибут указывает, должно ли условие соответствовать, если свойство недоступно .

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

@Test
public void whenValueSetToEmail_thenCreateEmailNotification() {
this.contextRunner.withPropertyValues("notification.service=email")
.withUserConfiguration(NotificationConfig.class)
.run(context -> {
assertThat(context).hasBean("emailNotification");
NotificationSender notificationSender = context.getBean(EmailNotification.class);
assertThat(notificationSender.send("Hello From ForEach!")).isEqualTo("Email Notification: Hello From ForEach!");
assertThat(context).doesNotHaveBean("smsNotification");
});
}

5. Вывод

В этой небольшой статье мы выделили цель использования аннотации @ConditionalOnProperty . Затем мы узнали, как использовать его для условной загрузки компонентов Spring на практическом примере.

Как всегда, полный исходный код этой статьи доступен на GitHub .