@conditional 注解家族实现按需加载 bean,核心包括 @conditionalonproperty(基于配置属性)、@conditionalonclass(检测类路径依赖)、组合条件(如避免覆盖用户 bean)及自定义 condition(跨维度判断),所有注解仅在被 spring 扫描的配置类中生效。

Spring Boot 的 @Conditional 注解家族是自动装配的核心支撑,它让 Bean 的注册不再“一刀切”,而是按需加载——比如只在 Linux 环境下启用某个监控组件,或仅当项目引入了 spring-boot-starter-data-redis 时才装配 RedisTemplate。关键在于把环境变量(如 spring.profiles.active、自定义 property)和类路径依赖(即 jar 包是否存在指定类)转化为可编程的判断逻辑。
用 @ConditionalOnProperty 控制环境相关 Bean
该注解直接读取配置项,适合基于 profile 或开关属性做装配决策。它不依赖操作系统或 JVM 层面信息,而是由 Spring Environment 统一管理,稳定且易测试。
- 支持精确匹配:
@ConditionalOnProperty(name = "app.feature.cache", havingValue = "true"),要求配置值严格等于字符串"true" - 支持 profile 组合:
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "prod", matchIfMissing = false),确保仅在 prod 环境生效 - 可设默认行为:
matchIfMissing = true表示若配置项未定义,条件仍成立(常用于兜底场景)
用 @ConditionalOnClass / @ConditionalOnMissingClass 检测 Jar 依赖
这是实现“有依赖才装配”的最常用方式。Spring Boot 自动配置大量使用它,例如只有 classpath 下存在 DataSource.class 才加载数据源自动配置。
-
@ConditionalOnClass(DataSource.class):检查当前类路径是否能加载到该类(不要求已实例化) -
@ConditionalOnMissingClass("com.mysql.cj.jdbc.Driver"):字符串形式更灵活,适用于类名含特殊字符或避免编译期强依赖 - 注意:它检测的是编译/运行时 classpath,不是 Maven 依赖声明本身;若 jar 被
provided作用域引入但未打入最终包,该条件可能不成立
组合多个条件:用 @ConditionalOnAllMissingBeans + @ConditionalOnProperty 实现安全覆盖
单一条件有时不够严谨。比如你希望“仅当未手动定义 RedisTemplate,且启用了 redis 功能”时才自动装配。这时需组合条件,避免覆盖用户自定义 Bean。
- 推荐写法:
@ConditionalOnClass(RedisTemplate.class)+@ConditionalOnProperty(name = "spring.redis.enabled", havingValue = "true", matchIfMissing = true)+@ConditionalOnMissingBean(RedisTemplate.class) - 三个条件必须同时满足,缺一不可,保障了装配的安全性与可控性
- 避免使用
@Conditional手动组合多个 Condition 实现类——除非有非常特殊的判断逻辑,否则优先选用现成的派生注解,语义清晰、维护成本低
自定义 Condition 实现跨维度判断(如 OS + Class 存在)
当需要同时校验环境变量和 jar 依赖(比如“Linux 系统且存在 netty-all.jar 才启用 native transport”),内置注解无法直接组合,此时应编写自定义 Condition。
- 实现
Condition接口,重写matches(ConditionContext context, AnnotatedTypeMetadata metadata) - 从
context.getEnvironment()获取 active profiles 或系统属性(如os.name) - 用
context.getClassLoader().loadClass(...)尝试加载目标类,捕获ClassNotFoundException判断 jar 是否就绪 - 再封装为派生注解,例如
@ConditionalOnLinuxAndNetty,提升复用性和可读性
不复杂但容易忽略:所有 @Conditional 相关注解都只在 Spring 扫描到的目标类或方法上起效,若配置类被 @ComponentScan 排除或未被任何 @Configuration 引用,条件逻辑根本不会执行。











