1. Overview
1.概述
In this short tutorial, we’ll examine the main purpose of the @ConditionalOnProperty annotation.
在这个简短的教程中,我们将研究@ConditionalOnProperty注解的主要目的。
First, we’ll start with a bit of background about what @ConditionalOnProperty is. Then we’ll look at some practical examples to help understand how it works and what features it brings.
首先,我们将先介绍一下什么是@ConditionalOnProperty的背景。然后我们将看一些实际的例子,以帮助理解它是如何工作的,以及它带来了哪些功能。
2. The Purpose of @ConditionalOnProperty
2.@ConditionalOnProperty的目的
Typically, when developing Spring-based applications, we need to create some beans conditionally based on the presence and value of a configuration property.
通常,在开发基于Spring的应用程序时,我们需要根据配置属性的存在和值,有条件地创建一些bean。
For example, we may want to register a DataSource bean to point to a production or test database depending on if we set a property value to “prod” or “test.”
例如,我们可能想注册一个DataSourcebean,使其指向生产或测试数据库,这取决于我们是否将一个属性值设置为 “prod “或 “test”。
Fortunately, achieving this isn’t as hard as it might look upon first glance. The Spring framework provides the @ConditionalOnProperty annotation precisely for this purpose.
幸运的是,实现这一点并不像乍看起来那么困难。Spring框架提供的@ConditionalOnProperty注解正是为了这个目的。
In short, the @ConditionalOnProperty enables bean registration only if an environment property is present and has a specific value. By default, the specified property must be defined and not equal to false.
简而言之,@ConditionalOnProperty只有在环境属性存在并且有特定值的情况下才会启用Bean注册。默认情况下,指定的属性必须被定义且不等于false。
Now that we’re familiar with the purpose of the @ConditionalOnProperty annotation, let’s dig deeper to see how it works.
现在我们已经熟悉了@ConditionalOnProperty注解的目的,让我们深入了解一下它是如何工作的。
3. The @ConditionalOnProperty Annotation in Practice
3.实践中的@ConditionalOnProperty注解
To exemplify the use of @ConditionalOnProperty, we’ll develop a basic notification system. To keep things simple for now, let’s assume that we want to send email notifications.
为了举例说明@ConditionalOnProperty的使用,我们将开发一个基本的通知系统。为了保持简单,我们假设我们想发送电子邮件通知。
First, we’ll need to create a simple service to send a notification message. For instance, consider the NotificationSender interface:
首先,我们需要创建一个简单的服务来发送通知信息。例如,考虑使用NotificationSender接口。
public interface NotificationSender {
String send(String message);
}
Next, let’s provide an implementation of the NotificationSender interface to send our emails:
接下来,让我们提供一个NotificationSender接口的实现来发送我们的电子邮件。
public class EmailNotification implements NotificationSender {
@Override
public String send(String message) {
return "Email Notification: " + message;
}
}
Now let’s see how to make use of the @ConditionalOnProperty annotation. Let’s configure the NotificationSender bean in such a way that it’ll only be loaded if the property notification.service is defined:
现在让我们看看如何利用@ConditionalOnProperty注解。让我们把NotificationSender Bean配置成只有在定义了notification.service这个属性时才会被加载。
@Bean(name = "emailNotification")
@ConditionalOnProperty(prefix = "notification", name = "service")
public NotificationSender notificationSender() {
return new EmailNotification();
}
As we can see, the prefix and name attributes are used to denote the configuration property that should be checked.
我们可以看到,prefix和name属性被用来表示应该被检查的配置属性。
Finally, we need to add the last piece of the puzzle. Let’s define our custom property in the application.properties file:
最后,我们需要添加拼图的最后一块。让我们在application.properties文件中定义我们的自定义属性吧。
notification.service=email
4. Advanced Configuration
4.高级配置
As we’ve already learned, the @ConditionalOnProperty annotation allows us to register beans conditionally depending on the presence of a configuration property.
正如我们已经学到的,@ConditionalOnProperty注解允许我们根据配置属性的存在有条件地注册bean。
However, we can do more than just that with this annotation. So let’s explore!
然而,我们可以用这个注解做得更多.,所以让我们来探索一下吧!
Let’s suppose we want to add another notification service, such as a service that will allow us to send SMS notifications.
假设我们想添加另一个通知服务,比如一个能让我们发送短信通知的服务。
To do that, we need to create another NotificationSender implementation:
要做到这一点,我们需要创建另一个NotificationSender的实现。
public class SmsNotification implements NotificationSender {
@Override
public String send(String message) {
return "SMS Notification: " + message;
}
}
Since we have two implementations, let’s see how we can use @ConditionalOnProperty to load the right NotificationSender bean conditionally.
既然我们有两个实现,让我们看看如何使用@ConditionalOnProperty来有条件地加载正确的NotificationSender Bean。
For this purpose, the annotation provides the havingValue attribute. Quite interestingly, it defines the value that a property must have in order for a specific bean to be added to the Spring container.
为此,该注解提供了havingValue属性。相当有趣的是,它定义了一个属性必须具有的值,以便特定的Bean被添加到Spring容器中。
Now let’s specify under which condition we want to register the SmsNotification implementation in the context:
现在让我们指定在哪个条件下我们要在上下文中注册SmsNotification实现。
@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
return new SmsNotification();
}
With the help of the havingValue attribute, we made it clear that we want to load SmsNotification only when notification.service is set to sms.
在havingValue属性的帮助下,我们清楚地表明,只有当notification.service被设置为sms时,我们才想加载SmsNotification。
It’s worth mentioning that @ConditionalOnProperty has another attribute called matchIfMissing. This attribute specifies whether the condition should match, in case the property isn’t available.
值得一提的是,@ConditionalOnProperty 还有一个名为matchIfMissing的属性。该属性指定了在该属性不可用的情况下,条件是否应该匹配。
Now let’s put all the pieces together, and write a simple test case to confirm that everything works as expected:
现在,让我们把所有的碎片放在一起,写一个简单的测试用例,以确认一切按预期工作。
@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. Conclusion
5.总结
In this brief article, we highlighted the purpose of using the @ConditionalOnProperty annotation. Then we learned how to use it to load Spring beans conditionally through a practical example.
在这篇简短的文章中,我们强调了使用@ConditionalOnPropertyannotation的目的。然后我们通过一个实际的例子了解了如何使用它来有条件地加载Spring Bean。
As always, the full source code for this article is available over on GitHub.
一如既往,本文的完整源代码可在GitHub上获得。