Spring Boot条件注解按判断维度分为六类:类路径(@ConditionalOnClass/@MissingClass)、Bean状态(@ConditionalOnBean/@MissingBean/@SingleCandidate)、配置属性(@ConditionalOnProperty)、应用类型(@ConditionalOnWebApplication/@NotWebApplication)、资源存在(@ConditionalOnResource)、SpEL表达式(@ConditionalOnExpression)及Java版本/JNDI环境(@ConditionalOnJava/@Jndi)。

要准确识别Spring Boot中可用的条件注解种类,不能只看注解名称表面,必须区分它们所依赖的判断维度——是看类路径、容器Bean、配置属性,还是运行环境本身。
按类路径是否存在判断
这类注解检查当前应用的 classpath 中是否包含指定类,常用于自动配置类中避免因缺少依赖而报错。
方法一:@ConditionalOnClass:当指定类(如 DataSource.class)在 classpath 中存在时生效。它常被用在 JPA、Redis、MyBatis 等 Starter 的自动配置类上,确保只有引入对应依赖才加载相关 Bean。
方法二:@ConditionalOnMissingClass:与前者相反,当指定类不存在时才生效。比如某些轻量级替代方案的自动配置,会先确认 Spring Data JPA 未被引入,再启用自定义 DAO 模式。
【注意:@ConditionalOnClass 可同时传入多个类,要求全部存在才满足条件;若只需存在其一,必须拆分成多个独立条件或改用 @Conditional + 自定义 Condition】
按Spring容器中Bean状态判断
这是最常用的一类,用于控制 Bean 的注册逻辑,尤其适合提供默认实现并允许用户覆盖的场景。
- 使用
@ConditionalOnBean:仅当容器中已存在指定类型(或名称)的 Bean 时,当前@Bean方法或配置类才生效。例如缓存配置类可能要求先有CacheManager实例。 - 使用
@ConditionalOnMissingBean:当容器中尚未注册指定类型的 Bean 时,才执行注册。Spring Boot 大量使用它来注入默认数据源、WebMvcConfigurer 等,避免用户自定义后重复创建。 - 使用
@ConditionalOnSingleCandidate:比@ConditionalOnBean更严格,要求容器中该类型 Bean 有且仅有一个。适用于需要唯一主 Bean 的场景,比如主数据源路由逻辑。
这三个注解都支持通过 value、name、search = SearchStrategy.ALL 等参数精细控制匹配范围。
按配置属性值判断
这类注解直接读取 application.properties 或 application.yml 中的键值,实现功能开关或环境差异化配置。
@ConditionalOnProperty 是唯一标准方案,必须指定 name 属性,例如 @ConditionalOnProperty(name = "app.feature.enabled")。若还需校验值,加上 havingValue = "true";若希望属性存在即生效,可省略 havingValue。
它支持 matchIfMissing = true 参数——当配置项根本没写时,也视为条件满足。这在提供“默认开启”功能时非常关键,否则未配置会导致功能静默失效。
按应用类型与运行环境判断
Spring Boot 需要区分 Web 应用与非 Web 应用,以加载不同的基础设施 Bean(如 Tomcat、DispatcherServlet、ReactiveWebServerFactory)。
方法一:@ConditionalOnWebApplication:当当前应用被识别为 Web 应用(即 classpath 含 Servlet API 且存在 Web 容器上下文)时生效。它内部调用 WebApplicationType.SERVLET 判断逻辑。
方法二:@ConditionalOnNotWebApplication:与之完全相反,适用于批处理、定时任务等纯后台服务场景,避免误加载 Web 相关组件。
这两个注解不依赖外部配置,完全由 Spring Boot 启动时自动推断得出,因此无法手动伪造或覆盖。
按资源文件是否存在判断
当你需要根据 classpath 下某个配置文件、模板文件或静态资源是否存在来决定是否启用某套逻辑时,用这个。
@ConditionalOnResource 接收一个 resources 字符串数组,例如 @ConditionalOnResource(resources = "classpath:banner.txt")。路径支持 classpath:、file: 前缀,但实际项目中几乎只用 classpath 形式。
注意:它只检测资源能否被 ResourceLoader 定位到,不校验内容是否为空或格式是否正确。
按SpEL表达式结果判断
这是灵活性最高的条件注解,适用于前述所有注解无法覆盖的复合判断场景。
@ConditionalOnExpression 直接执行 SpEL 表达式,例如 @ConditionalOnExpression("#{systemProperties['os.name'].toLowerCase().contains('win')}") 可用于 Windows 特有逻辑。
表达式内可访问 systemProperties、systemEnvironment、beanFactory 等上下文对象,但要注意避免在 matches() 中触发 Bean 创建循环依赖。
按Java版本或JNDI环境判断
这两类属于低频但关键的基础设施适配注解。
@ConditionalOnJava 支持 Range 枚举(EQ、GT、GTE、LT、LTE),例如 @ConditionalOnJava(range = Range.GTE, value = JavaVersion.EIGHT) 可限定最低 JDK 版本。
@ConditionalOnJndi 检查当前环境是否具备 JNDI 查找能力,多见于传统企业应用服务器(如 WebLogic、WebSphere)部署场景,普通 Spring Boot 内嵌容器默认不启用 JNDI。

















