💖简介
@Conditional
是 Spring
框架中用于条件化注册 Bean
的核心注解,它允许开发者根据特定条件决定是否将某个Bean
注册到 Spring
容器中。这一机制在实现多环境配置、模块化加载、动态依赖管理等场景中非常有用。
📖作用
-
条件控制:根据预设条件(如环境变量、类路径、系统属性等)动态决定是否创建并注册
Bean
。 -
灵活配置:避免硬编码配置,使应用能自适应不同的运行环境。
-
模块配置:通过条件控制模块的加载,例如仅在启用某些功能时注册相关
Bean
。
👉实现
- 定义条件类:实现
org.springframework.context.annotation.Condition
接口,并重写其matches
方法。在这个方法中,你可以定义判断条件的逻辑。如果条件满足,则返回true
;否则返回false
。
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class MyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 在这里实现你的条件逻辑// 返回 true 表示条件满足,Spring 将会创建该 Bean;反之则不创建。// 示例:假设我们只在系统属性 "my.condition" 设置为 "enabled" 时创建 BeanString conditionValue = System.getProperty("my.condition");return "enabled".equals(conditionValue);}
}
- 使用
@Conditional
注解:在你想要有条件的创建的Bean
上添加 @Conditional 注解,并指定你在第一步中定义的条件类。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyConfiguration {@Bean@Conditional(MyCondition.class) // 指定自定义的条件类public MyService myService() {return new MyServiceImpl();}
}
- 可以结合自定义注解,实现更为丰富的自定义功能
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import org.springframework.context.annotation.Conditional;// 定义注解的作用目标和生命周期
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(MyCondition.class) // 指定条件类
public @interface ConditionalOnMyCondition {
}
⚡原生
在Spring Boot
中,@Conditional
注解及其一系列衍生注解被广泛用于根据不同的条件来控制 Bean
的创建。Spring Boot
提供了许多预定义的条件注解,这些注解简化了基于条件的配置过程。以下是一些常见的使用场景和对应的注解:
-
@ConditionalOnClass
和@ConditionalOnMissingClass
:这些注解根据类路径中是否存在特定的类来决定是否应用某个配置或创建某个Bean
。 -
@ConditionalOnBean
和@ConditionalOnMissingBean
:基于Spring
容器中是否存在特定类型的Bean
来决定是否应用配置或创建新的Bean
。 -
@ConditionalOnProperty
:根据配置文件中的属性值来决定是否加载某些Bean
。这对于启用或禁用特定功能非常有用。 -
@ConditionalOnResource
:当指定的资源(如文件)存在于类路径中时,才加载相应的配置或Bean
。 -
@ConditionalOnWebApplication
和@ConditionalOnNotWebApplication
:根据应用是否为Web
应用来决定是否应用某些配置。这对于区分处理Web
和非Web
相关的Bean
配置特别有用。 -
@ConditionalOnExpression
:根据SpEL
表达式的计算结果来决定是否应用配置或创建Bean
。 -
@ConditionalOnJava
:基于Java
运行时版本来决定是否应用某些配置。 -
@ConditionalOnJndi
:如果JNDI
资源存在,则应用相关配置。 -
@ConditionalOnSingleCandidate
:当容器中有且仅有一个指定类型的主Bean
时,才应用相关的配置或创建Bean
。
⭐使用场景
-
环境区分:在不同的环境中(如开发、测试、生产)加载不同的
Bean
实现。例如,可以基于@Profile
注解实现这一点,但@Conditional
提供了更灵活的方式。 -
类存在性检查:根据某个特定类是否存在于类路径上来决定是否创建某些
Bean
。这对于处理可选依赖特别有用。Spring Boot
的@ConditionalOnClass
就是这样一个例子。 -
属性检查:根据配置文件中的属性值来决定是否创建某个
Bean
。例如,如果某个配置项被设置为特定值,则创建相应的Bean
。Spring Boot
提供了@ConditionalOnProperty
来简化这种场景的处理。 -
资源可用性:根据外部资源的可用性来决定是否创建
Bean
。例如,只有当数据库连接可用时才创建数据访问相关的Bean
。 -
运行时检查:基于系统属性或环境变量等运行时信息来控制
Bean
的创建。这允许应用程序根据部署环境的特性调整自身行为。 -
Bean 存在性检查:根据容器中是否已经存在某个
Bean
来决定是否创建另一个Bean
。这对于解决Bean
之间的依赖关系很有用。 -
自定义条件逻辑:对于一些复杂的条件判断逻辑,可以通过实现
Condition
接口来自定义条件评估逻辑,然后通过@Conditional
注解应用这些自定义条件。
结束