spring boot 2.x升3.x时自动配置迁移最易出问题的是spring.factories废弃后未迁移到autoconfiguration.imports,导致配置静默失效;需手动删除所有spring.factories文件,并严格按格式(每行一个全限定类名、无空行注释空格)编写imports文件,同时确保第三方starter及自定义配置类兼容jakarta命名空间与反射要求。

Spring Boot 2.x 升级到 3.x 时,自动配置迁移最容易出问题的地方不是代码逻辑本身,而是那些隐藏在 classpath 下、由 starter 自动触发却不再兼容的配置类——它们不会报编译错误,但会在启动时静默失效或抛出 NoSuchBeanDefinitionException。
spring.factories 文件必须删除
Spring Boot 2.x 中,自定义自动配置通过 META-INF/spring.factories 声明:org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.MyConfig。
Spring Boot 3.x 已彻底废弃该机制,改用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,且只接受全限定类名,一行一个。
若保留 spring.factories,它会被完全忽略,但 IDE 或构建工具可能不提示,导致你反复检查代码却找不到配置没生效的原因。
手动删除项目中所有模块下的 META-INF/spring.factories 文件——包括 test/resources 和第三方 jar 解压后残留的副本。
AutoConfiguration.imports 文件写法有硬性要求
方法一:直接写类名(推荐)
在 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中,每行写一个自动配置类的完整类名:
com.example.config.WebMvcAutoConfiguration
com.example.config.DataSourceAutoConfiguration
注意:不能带空行、不能有注释、不能有多余空格,否则整个 imports 文件被跳过,且无日志提示。
方法二:使用条件类(需谨慎)
如果原配置依赖 @ConditionalOnClass 或 @ConditionalOnMissingBean,这些注解在 3.x 中仍有效,但必须确保条件类本身也已迁移到 jakarta.* 包下——例如 @ConditionalOnClass(DataSource.class) 没问题,但若引用了 javax.sql.DataSource 就会因类加载失败导致条件永远为 false。
第三方 Starter 的自动配置未适配是最大雷区
第一步:运行 mvn dependency:tree -Dincludes=org.springframework.boot,确认所有 starter 版本号是否 ≥ 对应 Spring Boot 3.x 的最低兼容版本。
第二步:重点检查以下 starter 是否已升级:
• spring-boot-starter-data-redis → 必须 ≥ 3.0.0,旧版会尝试注册 javax.cache.annotation.Cacheable 导致启动失败
• mybatis-spring-boot-starter → 必须 ≥ 3.0.0,否则 SqlSessionFactoryBuilder 使用 javax.transaction 而非 jakarta.transaction
• spring-boot-starter-security → 必须 ≥ 3.0.0,否则 WebSecurityConfigurerAdapter 已移除,且默认启用 CSRF 保护,未显式禁用会导致所有 POST 请求 403
第三步:对每个含自动配置的第三方 jar,解压查看其 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 内容——若为空或不存在,说明该 starter 尚未适配 Spring Boot 3.x,必须更换为官方维护的 3.x 兼容版本。
【关键前提】 所有自定义 AutoConfiguration 类必须声明为 public static class,且所在 outer class 不能是 final 或 private,否则 Spring Boot 3.x 的反射加载器会跳过它。











