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 .