AutoConfigurationImportSelector 在调用 getAutoConfigurationEntry() 时真正触发 @Conditional 判断,它批量解析所有自动配置类上的条件注解并决定是否注册 BeanDefinition。

Spring Boot 启动时谁真正触发了 @Conditional 判断?
不是 @SpringBootApplication,也不是 SpringApplication.run() 本身,而是 AutoConfigurationImportSelector 在启动流程中调用 getAutoConfigurationEntry() 时,才真正开始批量解析和执行所有 @Conditional 系列注解的匹配逻辑。
这个类是自动配置的「闸门」:它先从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(或旧版 spring.factories)读取全部候选配置类,再逐个检查每个类上标注的 @ConditionalOnClass、@ConditionalOnBean 等是否满足——不满足就直接跳过,不会注册任何 @Bean 方法。
-
@ConditionalOnClass(DataSource.class)的判断发生在类加载阶段,不是运行时查 Spring 容器里有没有这个 Bean,而是看当前 ClassLoader 能否成功loadClass("javax.sql.DataSource") -
@ConditionalOnBean(name = "dataSource")实际上也**不是**在当前容器中查找已存在的 Bean,而是在「已注册的 Configuration 类解析完成前」,基于 BeanDefinition 注册顺序做静态推断(Spring Boot 2.6+ 后行为更严格,依赖BeanDefinitionRegistry中已注册的定义) - 所有条件注解的
matches()调用都发生在 IOC 容器刷新(refresh())之前的ConfigurationClassPostProcessor阶段,此时容器还几乎为空
@ConditionalOnClass 和 @ConditionalOnMissingClass 容易误判的两个场景
这两个注解看似简单,但实际行为和直觉有偏差,尤其在模块化或 classpath 混乱时。
- 如果类在 classpath 上存在,但被
module-info.java显式封禁(如 JDK 9+ 模块系统未导出),@ConditionalOnClass仍会返回true—— 因为它只调用ClassLoader.loadClass(),不校验模块可见性 -
@ConditionalOnMissingClass("com.example.FooService")不会阻止同名但不同包的类(如org.example.FooService)存在导致的误判;它只检查「指定全限定名」是否能被加载 - 使用
@ConditionalOnClass检查接口时,只要该接口类文件存在即满足,不关心是否有实现类或是否被实际引用
为什么 @ConditionalOnBean 在 @Configuration 类上无效?
因为 @ConditionalOnBean 的作用目标必须是「待注册的 Bean 定义」,而 @Configuration 类本身是一个配置源(ConfigurationClass),不是要注入的 Bean。把它加在类上,Spring 会忽略该条件,直接加载整个类(除非同时配了其他生效的条件注解,如 @ConditionalOnClass)。
- 正确用法:只加在
@Bean方法上,例如@Bean @ConditionalOnBean(DataSource.class) JdbcTemplate jdbcTemplate() - 错误写法:
@Configuration @ConditionalOnBean(DataSource.class) public class MyConfig { ... }—— 此时条件不生效,类总会被加载 - 若想控制整个配置类的加载,应优先使用
@ConditionalOnClass或@ConditionalOnProperty,它们天然支持类级别
调试 Condition 匹配失败最有效的手段
别靠猜,直接启用 Spring Boot 的自动配置报告,它会明确告诉你哪些配置类被跳过、原因是什么。
- 启动时加参数:
--debug或设置logging.level.org.springframework.boot.autoconfigure=DEBUG - 启动后访问
/actuator/autoconfig(需引入spring-boot-starter-actuator并暴露端点) - 关键输出字段:
positiveMatches表示满足条件并加载的配置,negativeMatches里会列出被跳过的类及具体不满足的条件,例如:"@ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.core.JdbcOperations'vs"did not find required class 'redis.clients.jedis.JedisPool'
真正卡住的地方,往往不是注解写错了,而是 classpath 缺少某个传递依赖,或者 spring.factories 被意外覆盖——这些信息在报告里一目了然。

















