SpringBoot 2.6.2升级2.7.0后@ConditionalOnBean判断异常问题
问题根因
这是Spring Boot 2.7版本自动配置加载逻辑收紧导致的顺序问题:
- 2.7版本重构了自动配置排序逻辑,严格按照
@AutoConfigureBefore/@AutoConfigureAfter声明的顺序执行配置类,移除了2.6版本中部分隐式的顺序兼容逻辑。 - 你当前的配置只声明了在
HibernateJpaAutoConfiguration、SecurityAutoConfiguration等配置之后加载,但没有声明在DataSourceAutoConfiguration之后加载。DataSourceBean本身是由DataSourceAutoConfiguration注册的,而非Hibernate相关配置。2.6版本因为排序逻辑宽松,你的配置加载时DataSource刚好已经完成注册,条件判断正常;2.7严格执行排序规则后,你的配置运行时DataSourceAutoConfiguration还未执行,容器中不存在DataSource的Bean定义,@ConditionalOnBean判定失败,直接阻断了配置类初始化。 - 额外注意:自动配置类上的类级别
@ConditionalOnBean只会检测当前配置执行前已经完成注册的Bean定义,不会感知后续加载的配置类要注册的Bean,因此显式声明加载顺序是这类条件注解生效的前提。
排查思路
- 启动时添加
--debug参数启动应用,查看控制台输出的自动配置评估报告,定位JpaAuditingSpringConfiguration的条件评估日志,会明确显示@ConditionalOnBean(DataSource.class)不通过的原因是未找到对应类型Bean,同时可以看到DataSource相关自动配置的加载顺序排在你的配置类之后。 - 对比2.6和2.7版本的自动配置评估报告,可直接看到两个版本下DataSource自动配置和你的审计配置的加载顺序差异。
- 检查自动配置注册文件:2.7版本开始支持从
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports读取自动配置类,如果你的配置仍只注册在旧的spring.factories中,可能不会被纳入新的自动配置排序链路,也会出现顺序错乱。
解决方案
方案1:修正自动配置加载顺序(推荐,向下兼容所有版本)
在@AutoConfigureAfter注解中补充DataSourceAutoConfiguration,显式保证当前配置在DataSource完成注册后再执行判断,原有业务逻辑完全不需要改动:
@Configuration @ConditionalOnBean(DataSource.class) @ConditionalOnClass({DataSource.class, AuditorAware.class, SecurityContextHolder.class}) // 补充DataSourceAutoConfiguration到后置加载列表 @AutoConfigureAfter({DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, SecurityAutoConfiguration.class, ClockSpringConfiguration.class}) @EnableJpaAuditing(auditorAwareRef = "auditorProvider", dateTimeProviderRef = "dateTimeProvider") public class JpaAuditingSpringConfiguration { @Bean public AuditorAware<String> auditorProvider() { return () -> Optional.ofNullable(SecurityContextHolder.getContext()) .map(SecurityContext::getAuthentication) .map(Authentication::getName); } @Bean public DateTimeProvider dateTimeProvider(Clock clock) { return () -> Optional.of(clock) .map(Clock::instant); } }
该修改完全兼容Spring Boot 2.6.x及更早版本,不会产生额外问题。
方案2:调整条件判断逻辑(适合不想维护加载顺序的场景)
如果不想显式绑定DataSource自动配置的顺序,可以将条件替换为基于JPA核心类存在的判断,通过JPA配置的前置依赖保证DataSource存在:
将类上的@ConditionalOnBean(DataSource.class)替换为@ConditionalOnClass(EntityManager.class)——JPA本身强依赖DataSource,只要EntityManager类存在且JPA自动配置生效,容器中必然已经注册了DataSource,同时将@AutoConfigureAfter调整为在JpaBaseConfiguration.class之后加载即可,同样可以实现“仅存在JPA运行环境(含DataSource)时配置生效”的需求。
内容的提问来源于stack exchange,提问作者Rainette
相关产品推荐
相关产品推荐

