《Spring Boot 入门》1.2 Spring Boot 4 带来了什么

本节围绕 Spring Boot 4.x 的破坏性变更展开:从 4.0 的模块化重构讲起,用本机 4.1.1 与 3.5.16 的真实启动日志对比包名变化,给出 Starter 改名表、Jackson 3 迁移要点与 Servlet 6.1 基线,再列出 4.1 的 gRPC、API Versioning 等新增能力,最后判断 4.x 适合谁用、什么场景该等一等。

本节目标:搞清 Spring Boot 4.0 与 4.1 究竟改了什么、哪些改动会伤到存量代码,并形成「4.x 现在能不能用」的判断。
适用版本:Spring Boot 4.1.x(Java 21)

1.2 Spring Boot 4 带来了什么

上一节末尾那支团队已经接受了「用 Boot 重构」,但紧接着冒出一个新问题:网上教程一半是 3.x、一半是 4.x,到底跟哪条线? 要回答这个,得先知道 4.x 和 3.x 的差距有多大。答案是:这是 Spring Boot 历史上少见的「大版本重构」,改动幅度接近 2.0 到 3.0 那次。

1.2.1 一次大版本的由来

Spring Boot 3.0(2022 年)的核心任务是 Jakarta 化:把 javax.* 全面换成 jakarta.*,并把基线抬到 Java 17。那次是「换命名空间」。

Spring Boot 4.0(2025 年)的任务是 模块化:把一个巨大的 spring-boot-autoconfigure 拆成几十个按技术划分的小模块。它要解决的是一个积累多年的结构问题——所有自动配置挤在一个 JAR 里,谁也不知道某段配置属于哪个技术、被谁引入。

这次重构带来两个直接后果:包名大面积变化、starter 大面积改名。这也是为什么 4.x 的学习资料看起来和 3.x「像但不完全像」。

1.2.2 最大的破坏性变更:模块化重构

在 3.x 里,几乎所有自动配置都躺在同一个模块 spring-boot-autoconfigure 中,根包是 org.springframework.boot.autoconfigure.*。4.0 把它按技术拆开,形成一套规整的三段式规则:

维度规则例子
模块名spring-boot-<technology>spring-boot-tomcat
根包名org.springframework.boot.<technology>org.springframework.boot.tomcat
Starter 名spring-boot-starter-<technology>spring-boot-starter-tomcat
测试模块spring-boot-<technology>-testspring-boot-jackson-test
测试包org.springframework.boot.<technology>.testorg.springframework.boot.jackson.test

这套规则一旦记住,你看到任何一个 4.x 的包名或 starter,都能立刻推断出它属于哪个技术。

另一个容易被忽略的影响:以前某些功能只需要引第三方依赖就能用,4.0 起必须显式引 starter。最典型的是数据库迁移工具:

<!-- 3.x:只引 Flyway 本体即可,Boot 会自动配置 -->
<dependency>
  <groupId>org.flywaydb</groupId>
  <artifactId>flyway-core</artifactId>
</dependency>

<!-- 4.x:必须引 starter,否则自动配置不生效 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-flyway</artifactId>
</dependency>

Liquibase 同理,改为 spring-boot-starter-liquibase。

1.2.3 实测日志里的证据

模块化到底改了什么?启动日志是最直接的证据。下面是我在本机(JDK 21.0.12.1 + Maven 3.9.12)跑 4.1.1 时,Tomcat 初始化那几行的真实输出:

2026-10-09T15:42:07.027+08:00  INFO 43496 --- [           main] o.s.boot.tomcat.TomcatWebServer          : Tomcat initialized with port 8080 (http)
2026-10-09T15:42:07.039+08:00  INFO 43496 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2026-10-09T15:42:07.039+08:00  INFO 43496 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/11.0.24]
2026-10-09T15:42:07.285+08:00  INFO 43496 --- [           main] o.s.boot.tomcat.TomcatWebServer          : Tomcat started on port 8080 (http) with context path '/'

注意 logger 名那一列:o.s.boot.tomcat.TomcatWebServer。同一段逻辑在 3.5.16 上,包名是旧的:

场景3.5.16 的 logger 名4.1.1 的 logger 名
Tomcat 启动o.s.b.w.embedded.tomcat.TomcatWebServero.s.boot.tomcat.TomcatWebServer
优雅停机o.s.b.w.e.tomcat.GracefulShutdowno.s.boot.tomcat.GracefulShutdown

o.s.b.w.embedded.tomcat 展开是 org.springframework.boot.web.embedded.tomcat,属于 3.x 的「一切都在 boot.web 下」。4.x 则把 Tomcat 相关全部归到 org.springframework.boot.tomcat 模块。包名变化不是审美问题,它意味着你的 logging.level 配置、日志过滤规则、甚至反射代码都可能需要同步改。

1.2.4 Starter 改名表

4.0 起,一批 starter 改了名。旧名仍然保留但已废弃,新项目应一律用新名:

废弃的旧名4.x 新名
spring-boot-starter-webspring-boot-starter-webmvc
spring-boot-starter-aopspring-boot-starter-aspectj
spring-boot-starter-oauth2-clientspring-boot-starter-security-oauth2-client
spring-boot-starter-oauth2-resource-serverspring-boot-starter-security-oauth2-resource-server
spring-boot-starter-oauth2-authorization-serverspring-boot-starter-security-oauth2-authorization-server
spring-boot-starter-web-servicesspring-boot-starter-webservices
spring-boot-starter-tomcat(war 部署)spring-boot-starter-tomcat-runtime

改名逻辑有迹可循:Web MVC 与 WebFlux 分家,所以 web 要明确成 webmvc;OAuth2 相关统一挂到 security 前缀下;web-services 去掉连字符。迁移期如果想少改代码,可以用过渡 starter:

<!-- 迁移期过渡:一次性把旧 starter 全部映射回新模块 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-classic</artifactId>
</dependency>

spring-boot-starter-test-classic 同理,用于测试侧。但过渡 starter 只是权宜之计,正式项目应尽早换成新名。

1.2.5 Jackson 3:影响面最广的一次升级

如果说模块化改的是「框架内部结构」,Jackson 3 改的就是「你每天写业务代码时会碰到的东西」。JSON 序列化在 Web 项目里无处不在,这次升级影响面极大。

项目3.x(Jackson 2)4.x(Jackson 3)
核心包名com.fasterxml.jacksontools.jackson
注解包com.fasterxml.jackson.annotation不变,仍在 com.fasterxml.jackson.annotation
自动配置用的类ObjectMapperJsonMapper / XmlMapper
自定义 builderJackson2ObjectMapperBuilderCustomizerJsonMapperBuilderCustomizer
组件注解@JsonComponent@JacksonComponent
Mixin 注解@JsonMixin@JacksonMixin

包名从 com.fasterxml.jackson 变成 tools.jackson(只有 jackson-annotations 例外,仍留在老包),这意味着你项目里所有 import com.fasterxml.jackson.databind.* 都要改。更关键的是行为变化:

  • 自定义 ObjectMapper bean 不再能替换自动配置。3.x 时代「自己 new 一个 ObjectMapper 塞进容器」就能覆盖默认行为,4.x 里这招失效,要改用 JsonMapperBuilderCustomizer。
  • 模块自动注册策略变了。Jackson 3 会扫描 classpath 上所有模块并注册,而 3.x 只注册知名模块。想关掉可设 spring.jackson.find-and-add-modules=false。
  • 属性重新分组:原来分散在 read/write 两组下的序列化属性,统一并入 spring.jackson.json.read / .write 命名空间。

如果迁移期实在被卡住,4.x 提供了逃生舱:

# 临时退回 Jackson 2 的行为(需额外引入 spring-boot-jackson2 模块)
spring:
  jackson:
    use-jackson2-defaults: true

1.2.6 平台基线整体抬升

4.x 不只是改包名,它把整条技术栈的基线都往上抬了一档。写代码前必须对齐这些前提:

组件4.x 基线3.5.x 对照
Java17+(本系列用 21)17+
Kotlin2.2+—
GraalVM native-image25+—
Jakarta EE1110
Servlet6.16.0
Spring Framework7.x6.2.x

Servlet 6.1 这个基线有个直接后果:一部分旧容器实现被淘汰,不再受支持。想用非 Tomcat 的容器,可选 Jetty 12.1。同时 Web MVC starter 默认内嵌的 Tomcat 版本也从 10.1 升到了 11.0。

Spring Framework 7.0 带来的配套大版本升级同样重要:Spring Security 7.0、Spring Data 2025.1、Hibernate 7.2、Hibernate Validator 9.0、HikariCP 7.0、Micrometer 1.16(4.1 为 1.17)。这些不是 Boot 自己的版本号,而是它协调好的一整组依赖——这正是 BOM 的价值。

1.2.7 4.0 的其他新增能力

除了重构与改名,4.0 也加了不少新东西:

  • HTTP Service Clients:用 @HttpExchange 接口式声明调用远程服务,取代手写 RestTemplate 模板代码。
  • API Versioning:通过 spring.mvc.apiversion.* 做接口版本管理,不用再自己拼 /v1/ 路径。
  • JmsClient:JMS 的现代化客户端。
  • spring-boot-starter-opentelemetry:可观测性能力进一步标准化。
  • @ConfigurationPropertiesSource:更细粒度地指定配置来源。
  • Kotlin Serialization starter:Kotlin 项目可以不用 Jackson。
  • RestTestClient:测试侧的新 HTTP 客户端。

这些能力中,API Versioning 与 HTTP Service Clients 对日常开发影响最大,后续章节会分别展开。

1.2.8 测试写法的同步迁移

大版本除了加功能,也会顺手清理历史包袱。对日常开发影响最直接的,是测试注解的更换。3.x 时代用来注入 Mock 与 Spy 的那两个注解已被彻底移除,取而代之的是 Mockito 系列的新注解,而且新注解不能用在 @Configuration 类里。

同时,@SpringBootTest 的行为也收紧了:它不再自动装配 MockMvc,也不再自动提供 TestRestTemplate。要写 Web 层测试,必须显式补上对应的自动配置注解:

@SpringBootTest
@AutoConfigureMockMvc          // 4.x 必须显式声明,否则 MockMvc 注入失败
class OrderControllerTest {

    @Autowired
    private MockMvc mockMvc;
}

4.x 还新增了 RestTestClient,配合 @AutoConfigureRestTestClient 作为测试侧 HTTP 客户端的新选择。这些变化集中体现在第 17 章的测试章节,本节先建立「4.x 的测试写法与 3.x 不同」这个印象。

除此之外,一批使用率偏低的集成方式与旧打包方式也在 4.0 被清理。涉及非 Tomcat 容器选型、消息驱动集成或自定义 jar 加载方式的团队,升级前需要先确认自己是否受影响,具体的迁移对照清单在第 11 章给出。

1.2.9 4.1 的新增亮点

如果说 4.0 是「重构」,4.1 更像「在重构后的地基上加功能」。本系列主线用的就是 4.1.x:

  • Spring gRPC 支持:官方首次把 gRPC 纳入一等公民,配 starter 即可。
  • Jackson 工厂配置与 customizer:补上 4.0 迁移时留下的自定义缺口。
  • spring.config.import 指定编码:解决配置文件乱码的老问题。
  • HTTP 客户端 cookie 配置:RestClient 等客户端可集中管理 cookie。
  • SSRF 防护 InetAddressFilter:为出站请求提供地址过滤,安全侧的重要补充。
  • @Async 上下文传播:异步线程能继承调用方的上下文。
  • @RedisListener 自动配置:Redis 消息监听更省事。
  • 惰性 JDBC 连接获取:spring.datasource.connection-fetch=lazy,配合虚拟线程时很有用。
  • OpenTelemetry 环境变量与 sampler/limits、info 端点扩展(process.*)、Log4j 文件轮转。

其中 gRPC 与 惰性 JDBC 连接获取 是两个值得单独留意的能力,前者打开了服务间通信的新选择,后者直接关系到虚拟线程场景下的连接池效率。

1.2.10 4.1 的额外破坏性变更

升级到 4.1 时,除了 4.0 的变更,还要注意:

  • 4.0 中废弃的类、方法、属性已被移除——也就是说,从 3.x 直接跳到 4.1 时,4.0 给的过渡期已经结束了。
  • layertools jar 模式移除,改用 tools 模式(涉及 Docker 分层构建脚本)。
  • -DskipTests 不再跳过测试的 AOT 处理,要跳过 AOT 得用 maven.test.skip。这条对用 AOT / native 的团队影响直接。
  • Apache Derby 支持废弃;jOOQ 3.20 要求 Java 21+。

1.2.11 那么,4.x 现在适合谁用

回到那支团队的选型问题。基于上面的清单,可以给出比较明确的判断:

场景建议
全新项目,团队能接受 Java 17+直接用 4.1.x。没有历史包袱,新名新写法一次到位
教学 / 学习用 4.1.x。学新不学旧,避免先学废弃写法再改
小规模存量项目,升级成本可控可以规划升 4.1,但先做依赖与 Jackson 影响面评估
重度依赖 Jackson 2 定制行为的项目谨慎,先把 ObjectMapper 定制改成 JsonMapperBuilderCustomizer 再升
依赖已被移除的低使用率功能先找替代方案,替代不了就留在 3.5.x

一句话:4.x 已经过了「能不能用」的阶段,现在的问题是「你的项目准备好没有」。

1.2.12 什么场景该等一等

不是所有团队都该立刻上 4.x。下面这些情况,留在 3.5.x 是理性选择:

  • 受监管行业、有强制版本冻结流程:新大版本还没经过完整的合规审查周期,贸然升级反而增加审计成本。
  • 深度使用已被移除的旧组件:迁移工作量大,收益不成正比。
  • 第三方生态尚未跟进:某些商业中间件、内部 SDK 可能还没适配 Servlet 6.1 或 Jackson 3。
  • 团队没有专职的构建/依赖负责人:大版本升级中的版本冲突排查需要有人专门盯。

需要说明的是:3.5.x 仍是受支持的分支,继续用并不等于落后。选型要算的是「升级成本」与「升级收益」的账,而不是「版本号大小」。

1.2.13 学完本节你应该能回答的问题

  • 4.0 模块化的三段式命名规则是什么?(1.2.2)
  • 从日志里怎么一眼看出项目跑在 3.x 还是 4.x?(1.2.3)
  • spring-boot-starter-web 在 4.x 叫什么?(1.2.4)
  • Jackson 3 里,为什么「自定义 ObjectMapper bean」不再生效?(1.2.5)
  • 4.x 的 Servlet 与 Jakarta EE 基线分别是多少?(1.2.6)
  • 哪三类项目适合立刻上 4.x,哪三类该等一等?(1.2.11、1.2.12)

把这几个问题答顺,你就具备了独立判断「这个项目能不能升 4.x」的能力,而不用再依赖别人的结论。

小结

  • Spring Boot 4.0 是一次模块化重构,按技术拆分了原本庞大的自动配置模块,带来包名与 starter 名的系统性变化。
  • 三段式规则:模块 spring-boot-<tech>、包 org.springframework.boot.<tech>、starter spring-boot-starter-<tech>;实测日志里 o.s.boot.tomcat.TomcatWebServer 就是证据。
  • Starter 改名中,Web MVC 从 web 变为 webmvc;迁移期可用 spring-boot-starter-classic 过渡。
  • Jackson 3 把包名迁到 tools.jackson,ObjectMapper 换成 JsonMapper,且自定义 bean 不再覆盖自动配置。
  • 平台基线抬到 Java 17+、Jakarta EE 11、Servlet 6.1、Spring Framework 7;部分旧容器实现被淘汰。
  • 4.1 在重构地基上加了 gRPC、API Versioning 相关增强、惰性 JDBC 连接获取等能力,但同时也移除了 4.0 的过渡接口。
  • 新项目与教学用 4.1.x;受监管、依赖已移除组件、生态未跟进的存量项目,留在 3.5.x 是理性选择。

知道了 4.x 改了什么,下一个问题自然是:3.5.x 与 4.1.x 到底差在哪几个具体数字上,我们该按什么标准二选一? 下一节给出逐项对照表和决策树。

阅读导航:上一节:1.1 定位、生态与它解决的问题 · 下一节:1.3 版本线的选择 。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java」更多文章

  1. 《Spring Boot 入门》18.3 打包与运行
  2. 《Spring Boot 入门》18.2 实现
  3. 《Spring Boot 入门》18.1 需求与设计