1、概览 {#1概览}
本文将带你了解 Spring 中 @ConditionalOnProperty
注解的作用和用法。
2、@ConditionalOnProperty 的作用 {#2conditionalonproperty-的作用}
通常,在开发基于 Spring 的应用时,需要根据配置属性是否存在,或者配置属性有指定的值来有条件地创建一些 Bean。
例如,我们需要注册一个 DataSource
Bean,并且要根据属性值设置为 prod
还是 test
来创建生产数据库或测试数据库。
这正是 @ConditionalOnProperty
注解的用武之地。
简而言之,@ConditionalOnProperty
只有在环境属性存在且具有指定值的情况下才会启用 Bean 注册。默认情况下,指定的属性必须已定义且等于指定的值。
熟悉了 @ConditionalOnProperty
注解的用途后,接着来深入了解一下如何使用。
3、@ConditionalOnProperty 注解实践 {#3conditionalonproperty-注解实践}
开发一个基本的电子邮件通知系统来示范 @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
注解。
以这样一种方式配置 NotificationSender
Bean:只有定义了 notification.service
属性,它才会被加载:
@Bean(name = "emailNotification")
@ConditionalOnProperty(prefix = "notification", name = "service")
public NotificationSender notificationSender() {
return new EmailNotification();
}
prefix
和 name
属性用于表示应检查的配置属性。
最后,在 application.properties
文件中定义自定义属性:
notification.service=email
4、高级配置 {#4高级配置}
如前所述,@ConditionalOnProperty
注解允许我们根据配置属性是否存在来有条件地注册 Bean。
@ConditionalOnProperty
注解能做的不仅于此。
假设我们想添加另一项通知服务,例如允许我们发送 SMS 通知的服务。
为此,创建另一个 NotificationSender
实现:
public class SmsNotification implements NotificationSender {
@Override
public String send(String message) {
return "SMS Notification: " + message;
}
}
既然我们有了两种实现,那么来看看如何使用 @ConditionalOnProperty
来有条件地加载正确的 NotificationSender
Bean。
为此,注解提供了 havingValue
属性。它定义了属性必须具有的值,以便将特定 Bean 添加到 Spring 容器中。
现在,指定在哪种情况下才在 Context 中注册 SmsNotification
实现:
@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
return new SmsNotification();
}
havingValue
属性表示,只有当 notification.service
配置属性的值设置为 sms
时,才会加载 SmsNotification
。
@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 Baeldung!")).isEqualTo("Email Notification: Hello From Baeldung!");
assertThat(context).doesNotHaveBean("smsNotification");
});
}
5、总结 {#5总结}
本文介绍了 @ConditionalOnProperty
注解的作用, 以及如何使用该注解来根据配置属性有条件地加载 Spring Bean。
Ref:https://www.baeldung.com/spring-conditionalonproperty