哈喽,大家好,我是呼噜噜,近期Spring Boot 4.0.0已于 2025年11月20日 正式发布。
这是一个重大的主版本更新,标志着 Spring Boot 进入了新一代。它基于 Spring Framework 7.0 构建,主要聚焦于对最新 Java 特性的支持(如 Java 25)、Jakarta EE 11 规范的对齐以及云原生能力的增强。
不禁感叹Spring Boot3都还没学完,Spring Boot 4就都来了

那我们来看看这次Spring Boot 4.0.0 大版本更新的核心信息有哪些:

核心基准
- Java 版本: 最低要求 Java 17,但官方强烈推荐使用 Java 25(LTS)以利用虚拟线程等最新特性
- Spring Framework: 基于 Spring Framework 7.0
- Jakarta EE: 全面升级到 Jakarta EE 11(Servlet 6.1, JPA 3.2, Bean Validation 3.1)
- Kotlin: 基准提升至 Kotlin 2.2
关键新特性
我们再来看看这次大版本更新,还有有哪些新特性
全面拥抱 JSpecify 空安全
空指针NullPointerException可以说是我们javaer经常遇到的痛苦了,生产环境一遇到,头皮发麻。
它就像隐藏在代码深处的定时炸弹,往往在程序运行时突然爆发,导致程序崩溃,而且还非常难以排查
Spring Boot 4.0 全面拥抱 JSpecify 空安全体系,它的核心就是,默认非空(@NullMarked)+ 明确标注可空(@Nullable),能够在编译阶段就发现潜在的 Null 指针风险,提前预警
在类或包上加一个 @NullMarked,里面所有引用类型默认都是非空的,只有明确标了 @Nullable 的才可能为 null。这样:
- 方法签名一目了然:返回值、参数到底会不会
null; - 配合
NullAway后,漏检查的地方直接编译失败; - 零运行时开销,完全兼容现有代码;
- 比
Optional更轻量、更适合做大规模重构。
@org.jspecify.annotations.NullMarked // 本 package 下默认所有类型为非 null
package com.example.demo.service; // 根据你自己包名写
// 注意:NullMarked 也可放在 class 上,
// 或者对整个 module/packageTree 生效。@NonNull:与 @Nullable 相反,@NonNull 注解用于强调某个元素绝对不能为 null:
@RestController
public class GreetingController {
private final GreetingService greetingService;
public GreetingController(GreetingService greetingService) {
this.greetingService = greetingService;
}
@GetMapping("/greet")
public @NonNull Map<String, @Nullable String> greet(
@RequestParam(required = false) @Nullable String name) { // name 可能为 null(用户没传),因此用 @Nullable
String greeting = greetingService.greet(name);
// greeting 按定义为非 null
return Map.of("greeting", greeting);
}
}API 版本控制
4.0版本中,API 版本控制变得更加原生和标准化,引入了在 @RequestMapping / @GetMapping 等注解中使用 version 属性的能力,并提供 ApiVersionConfigurer 等工具来解析版本(支持 path/header/query/media-type)
- 控制器示例(v1 / v2)
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping(path = "/", version = "1") //匹配 /api/user?version=1 或配置路径映射
public Map<String, Object> getUsersV1() {
return Map.of("version", "v1", "data", "user-list-v1"); // 返回示例
}
@GetMapping(path = "/", version = "2") // 版本 2 的映射
public Map<String, Object> getUsersV2() {
return Map.of("version", "v2", "data", "user-list-v2"); // 返回示例
}
}application.properties配置示例
@Configuration // 标注为配置类
public class ApiVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) { // 配置 API 版本化策略
configurer.useHeader("API-Version"); // 指定从 header 名称 API-Version 中读取版本
configurer.setVersionRequired(false); // 当没有提供版本时,允许兼容所有版本(false)或强制要求版本(true)
}
}只需修改application.properties,就能切换策略,就能轻松实现URI前缀、Header或参数驱动的版本路由
spring.mvc.apiversion.use.header=API-Version
spring.mvc.apiversion.default=1声明式HTTP客户端
Spring Boot 4 对 HTTP Service Clients 提供了自动配置支持,允许我们用接口 + 注解声明远端调用(类似 Feign,但以 Spring 的风格)
比如使用HttpExchange注解,代码量减少60%。再也不用通过RestTemplate 或 WebClient来手写 HTTP 调用的实现类:
@HttpExchange(url = "https://echo.zuplo.io")
public interface EchoService {
@PostExchange("/post")
Map<String, Object> echo(@RequestBody Map<String, String> body);
}
@Service
public class EchoBusinessService {
private final EchoService echoService; // 客户端接口作为依赖
@Autowired // 构造器注入
public EchoBusinessService(EchoService echoService) {
this.echoService = echoService;
}
public Map<String,Object> echoOnce() {
Map<String,String> payload = Map.of("message", "hello");
return this.echoService.echo(payload); // 调用远端并返回结果
}
}大家可以细心品味,接口式客户端的声明与调用,非常类似于 Feign 的体验
Spring Boot 4 的自动配置会在运行时生成实现并使用底层 WebClient。具体注解名与语义以 Spring Framework 7/Boot4 的文档为准
弃用Undertow
之前国内软件行业掀起用Undertow替换tomcat的浪潮,但现在Spring Boot 4.0.0 移除了对 Undertow 支持
我们来看一下有哪些原因:
- 规范适配滞后:
Undertow未及时适配Servlet 6.1规范,无法满足Jakarta EE 11基线要求。 - 维护团队能力不足:
Undertow核心维护者仅3-5人,且存在人员流失,2023-2024年核心功能迭代周期从 2 个月延长至 6 个月以上。 - 适配成本过高:为兼容
Spring Boot 3.x的Jakarta EE 9+、AOT编译等特性,Spring Boot团队为Undertow投入30%的兼容性测试资源,远超Tomcat(5%)与Jetty(8%)。 - 性能优势消失:通过
JMeter测试,Tomcat 10.1.18与Undertow 2.3.10.Final性能相差无几,在现代 JVM 优化下,Undertow的 “低内存、高并发” 优势已不明显

虚拟线程支持
基于 Java 21的虚拟线程特性,Spring Boot 4.0.0 重构线程池模型,实现 “百万级并发” 支持:
- 异步处理优化:在支付网关场景中,
每秒请求处理量RPS从1.2万提升至8.5万,CPU占用率下降40% - 无缝启用:通过
spring.threads.virtual.enabled=true全局启用,原有@Async注解无需修改 - 监控增强:
Actuator新增/virtual-threads端点,实时监控线程状态与阻塞事件
// 全局启用虚拟线程
spring:
threads:
virtual:
enabled: true
// 异步任务无需修改
@Async
public CompletableFuture<String> fetchData() {
return CompletableFuture.completedFuture("Data from virtual thread");
}新版本也正式提供对 Java 25 的顶级支持(LTS 版本 Java 17 依然兼容)
可观测性增强:Micrometer + Tracing
Spring Boot 4 更新了 Micrometer 版本并加强了 observability(包含 tracing 与更丰富的 auto-config)。
接下来,我们在注册指标和在关键路径添加 tracing span:
@Component
public class MyMetrics {
private final Counter requestCounter; // 计数器字段
private final Tracer tracer; // tracer 字段
@Autowired
public MyMetrics(MeterRegistry registry, Tracer tracer) { // 构造器注入:MeterRegistry 与 Tracer
this.requestCounter = Counter.builder("myapp.requests") // 创建名为 myapp.requests 的计数器
.description("Number of requests processed")
.register(registry); // 注册到 MeterRegistry
this.tracer = tracer;
}
public void onRequest() {
this.requestCounter.increment(); // 每次请求时计数器加一
Span span = this.tracer.nextSpan().name("my.custom.span");
try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) {
// 在这个 try 块中进行你想要跟踪的逻辑
} finally {
span.end(); // 结束 span
}
}
}迁移建议
最后说一下迁移建议,可以不用太着急升级,再等待其他配置组件都适配SpringBoot4.0。先落脚 Spring Boot 3.5.x,再迈向 4.0 的云原生世界,方能以最小成本,平稳升级,享受虚拟线程、原生镜像带来的性能红利。
点击"在看"并关注我,获取更多前沿技术解读与实战干货!
如果你对SpringBoot4.0.0的发布,有任何看法,欢迎在评论区留言呀
参考资料:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Release-Notes
作者:小牛呼噜噜
本文到这里就结束啦,感谢阅读,关注同名公众号:小牛呼噜噜,防失联+获取更多技术干货