一、简介
在本教程中,我们将看看@Conditional注释。它用于根据定义的条件指示给定组件是否有资格注册。
我们将学习如何使用预定义的条件注释,将它们与不同的条件结合起来,以及创建我们自定义的、基于条件的注释。
2.使用Conditional注释
在我们进入实现之前,让我们首先看看我们可以在哪些情况下使用条件注释。
最常见的用法是包含或排除整个配置类:
@Configuration @Conditional(IsDevEnvCondition.class) class DevEnvLoggingConfiguration { // ... }
或者只是一個 bean:
@Configuration class DevEnvLoggingConfiguration { @Bean @Conditional(IsDevEnvCondition.class) LoggingService loggingService() { return new LoggingService(); } }
通过这样做,我们可以将应用程序的行为基于给定的条件。例如,我们客户的环境类型或特定需求。在上面的例子中,我们只为开发环境初始化了额外的日志服务。
使组件有条件的另一种方法是将条件直接放在组件类上:
@Service @Conditional(IsDevEnvCondition.class) class LoggingService { // ... }
我们可以将上面的例子应用于任何用@Component 、 @Service 、 @Repository,或@Controller注释声明的 bean。
3. 预定义的条件注释
Spring 带有一组预定义的条件注释。让我们来看看一些最受欢迎的。
首先,让我们看看如何基于配置属性值构建组件:
@Service @ConditionalOnProperty( value="logging.enabled", havingValue = "true", matchIfMissing = true) class LoggingService { // ... }
第一个属性value,告诉我们要查看的配置属性。第二个, havingValue,定义了这个条件所需的值。最后, matchIfMissing属性告诉 Spring 如果缺少参数,是否应该匹配条件。
同样,我们可以将条件基于表达式:
@Service @ConditionalOnExpression( "${logging.enabled:true} and '${logging.level}'.equals('DEBUG')" ) class LoggingService { // ... }
现在,只有在logging.enabled配置属性设置为true,并且logging.level设置为DEBUG.时,Spring 才会创建LoggingService
我们可以应用的另一个条件是检查是否创建了给定的 bean:
@Service @ConditionalOnBean(CustomLoggingConfiguration.class) class LoggingService { // ... }
或者类路径上存在给定的类:
@Service @ConditionalOnClass(CustomLogger.class) class LoggingService { // ... }
@ConditionalOnMissingBean或@ConditionalOnMissingClass注释来实现相反的行为。
此外,我们可以将组件依赖于给定的 Java 版本:
@Service @ConditionalOnJava(JavaVersion.EIGHT) class LoggingService { // ... }
在上面的例子中, LoggingService只会在运行时环境为 Java 8 时被创建。
最后,我们可以使用@ConditionalOnWarDeployment注解来只在war包中启用bean:
@Configuration @ConditionalOnWarDeployment class AdditionalWebConfiguration { // ... }
请注意,对于带有嵌入式服务器的应用程序,此条件将返回 false。
4.定义自定义条件
Spring 允许我们通过创建自定义条件模板来自定义@Conditional注释的行为。要创建一个,我们只需要实现Condition接口:
class Java8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT); } }
matches方法告诉Spring条件是否已通过。它有两个参数,分别为我们提供有关 bean 将初始化的上下文和使用的@Conditional注释的元数据的信息。
如我们所见,在我们的示例中,我们只检查 Java 版本是否为 8。
之后,我们应该将我们的新条件作为@Conditional注释中的一个属性:
@Service @Conditional(Java8Condition.class) public class Java8DependedService { // ... }
这样, Java8DependentService将仅在从条件创建Java8Condition类匹配。
5.合并条件
对于更复杂的解决方案,我们可以使用 OR 或 AND 逻辑运算符对条件注释进行分组。
要应用 OR 运算符,我们需要创建一个扩展AnyNestedCondition类的自定义条件。在其中,我们需要static类,并使用适当的@Conditional实现对其进行注释。
例如,让我们创建一个需要 Java 8 或 Java 9 的条件:
class Java8OrJava9 extends AnyNestedCondition { Java8OrJava9() { super(ConfigurationPhase.REGISTER_BEAN); } @Conditional(Java8Condition.class) static class Java8 { } @Conditional(Java9Condition.class) static class Java9 { } }
另一方面,AND 运算符要简单得多。我们可以简单地将条件分组:
@Service @Conditional({IsWindowsCondition.class, Java8Condition.class}) @ConditionalOnJava(JavaVersion.EIGHT) public class LoggingService { // ... }
在上面的例子中, IsWindowsCondition和Java8Condition都匹配时才会创建LoggingService
0 评论