@ConditionalOnClass通过ClassLoader.loadClass()动态加载类来判断存在性,而非静态扫描;其在parse_configuration阶段触发,要求所有指定类均能成功加载才满足条件。

要让 Spring Boot 在启动时准确判断某个类是否存在于类路径中,必须理解 @ConditionalOnClass 的真实工作方式——它不是扫描 jar 包或读取 class 文件,而是尝试用当前 ClassLoader 加载目标类。
@ConditionalOnClass 实际触发时机
Spring Boot 启动过程中,当 Configuration 类被解析时(即 parse_configuration 阶段),遇到 @ConditionalOnClass 注解,会立即调用其对应的 OnClassCondition.matches() 方法。
该方法内部执行 ClassUtils.isPresent(className, getClassLoader()),本质是调用 ClassLoader.loadClass(String name)。
只要不抛出 ClassNotFoundException 或 NoClassDefFoundError,就视为类存在;哪怕该类所在 jar 没有被依赖传递进来、或仅在 test scope 下,只要运行时 classpath 中能 load 到,条件即满足。
两种写法的加载行为差异
方法一:使用 Class 类型参数
@ConditionalOnClass(DataSource.class) → 编译期就能校验 DataSource 是否可访问,IDE 可提示、拼写错误会在编译时报出,推荐在项目内已有依赖时使用。
方法二:使用字符串类名参数
@ConditionalOnClass(name = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration") → 绕过编译期检查,适用于目标类尚未引入依赖(如可选模块)、或类名来自第三方未导出包的情况;但写错全限定名不会编译报错,只有启动时才失败。
【name 属性值必须是运行时实际存在的类全限定名,不能是接口、抽象类别名或不存在的别名】
多类判断的逻辑顺序
第一步:@ConditionalOnClass({JdbcTemplate.class, DataSource.class}) 要求两个类全部存在才通过。
第二步:Spring 会按数组顺序依次尝试加载每个类,一旦某个类加载失败(ClassNotFoundException),立刻中断并返回 false,后续类不再检查。
第三步:即使 JdbcTemplate 所在的 spring-jdbc.jar 已引入,但 DataSource 来自 spring-boot-autoconfigure,若该 jar 未出现在最终 classpath(例如 Maven 依赖被 exclude),整个条件仍不满足。
这一步没有缓存机制,每次 matches() 调用都重新执行 loadClass,所以类路径变动后重启应用才生效。









