@conditional 是 spring boot 在 bean 定义注册阶段按条件决定是否将 bean 加入容器的核心机制,通过 conditionevaluator 调用 matches() 方法实现早筛;常用注解包括 @conditionalonproperty、@conditionalonclass、@conditionalonbean、@conditionalonwebapplication 等,支持自定义 condition,并与 @profile 职责分明、可组合使用。

@Conditional 是 Spring Boot 实现按需动态注入的核心机制,它不是在 Bean 创建时才判断,而是在 Bean 定义注册阶段就决定“这个 Bean 到底要不要进容器”。只要条件不满足,Spring 就当它不存在——不会实例化、不会依赖注入、也不会参与后续任何流程。
条件注解发生在 Bean 注册之前
Spring 启动时扫描到一个 @Configuration 类或 @Bean 方法后,会先检查其上的 @Conditional 系列注解。此时 Bean 还没创建,甚至类都还没实例化。Spring 通过 ConditionEvaluator 调用对应 Condition 实现的 matches() 方法:
- 返回 true → 继续解析该类/方法,生成 BeanDefinition 并注册进容器
- 返回 false → 直接跳过,整个过程就像这段代码没写过一样
这种“编译期不可见、运行期早筛”的设计,让自动配置既轻量又安全。
常用条件注解及其典型用途
Spring Boot 预置了大量开箱即用的条件注解,覆盖绝大多数动态注入场景:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
@ConditionalOnProperty:根据 application.yml 或 application.properties 中的属性值控制开关,比如
@ConditionalOnProperty(name = "app.feature.sms.enabled", havingValue = "true") - @ConditionalOnClass / @ConditionalOnMissingClass:检查类路径是否存在某类,常用于“有依赖才加载对应配置”,如 JPA 自动配置会先确认 EntityManager 是否在 classpath
- @ConditionalOnBean / @ConditionalOnMissingBean:依据容器中已有 Bean 的存在与否做决策,适合提供默认实现或避免重复注册,例如默认数据源只在用户没声明 DataSource Bean 时才生效
- @ConditionalOnWebApplication:区分 Web 环境与非 Web 环境,确保 Filter、Servlet 等组件仅在 Web 应用中加载
自定义条件判断也很简单
如果内置注解不够用,可以快速实现自己的 Condition:
- 写一个类实现
Condition接口,重写matches()方法 - 利用
ConditionContext获取 Environment(读配置)、ClassLoader(查类)、BeanFactory(查已有 Bean)等上下文信息 - 在 @Conditional 中引用该类,例如
@Conditional(MyCustomCondition.class)
比如检查某个系统属性是否为 true,或验证外部配置中心返回的开关状态,都可以在这里统一处理。
注意和 @Profile 的区别
@Profile 控制的是“在哪种环境生效”,比如 dev/test/prod;而 @Conditional 控制的是“这个功能有没有被启用”。两者可以共存,但职责不同:
- 用 @Profile 区分环境差异(如数据库连接地址)
- 用 @Conditional 控制模块开关(如是否启用邮件服务、是否加载 Redis 缓存支持)
一个典型的组合是:@Configuration @Profile("prod") @ConditionalOnProperty("mail.enabled"),表示“只在生产环境且邮件功能开启时,才加载邮件相关配置”。










