还记得 2022 年底不?当时Spring Boot 3 和 Spring Framework 6 一出来,直接给整个 Spring 生态来了个 “大换血”, 这可是自 Spring 诞生以来动静最大的一次更新。不仅把 Java 17 设为了最低要求,还把以前的 javax.* 换成了 jakarta.*,连 GraalVM 原生镜像也开始初步支持了。
转眼到 2025 年,新一代版本马上要来了:就是 Spring Boot 4 和 Spring Framework 7。
这俩版本没跑偏,接着推进生态现代化。一方面用上了最新的 Java 特性,跟 Jakarta EE 11 的适配也更紧密;另一方面还帮开发者省了不少事,而且默认就支持打造 “抗造” 的应用,不用额外折腾太多。
接下来我就跟大家捋捋这俩版本的核心亮点,再配点说明和代码例子,让大家清楚升级后能用到啥好东西。
基线升级
在说具体功能之前,得先明确新版本对 “基础依赖” 的要求,这很关键。
现在行业里用 Java 17 的还挺多,所以它依然是最低要求版本。不过官方特别建议用 Java 21 或 25,因为能用上虚拟线程这类新的 JVM 特性。关于这点,Spring 博客里有官方说明,大家想细看可以去那看。
Spring Framework 7 现在完全适配 Jakarta EE 11 了,也就是说,它依赖的技术标准都升级了:Servlet 6.1、JPA 3.2,还有 Bean Validation 3.1。
另外,Kotlin 现在支持 2.2 及以上版本了。这么一来,写协程会更顺,处理响应式代码也感觉更 “自然”,不用绕弯子。
Spring Boot 4
作为第四个大版本,Spring Boot 这次加了不少实用改进,重点提一下:性能变快了、更容易 “监控” 应用了、维护起来更省心了,连配置支持都变强了。这些改动让它作为 “现代云原生 Java 应用的基础框架”,地位更稳了。
原生镜像更给力了
Spring Boot 4 还在使劲推进 GraalVM 原生镜像的支持,现在已经完全跟 GraalVM 24 对齐了。而且 “提前编译(AOT)” 的能力也优化了 —— 编译速度更快,启动时占的内存也更少了。
举个例子,Spring Data 新增了AOT 仓库,简单说就是:通过 AOT 处理,能把查询方法转成源代码,然后跟应用一起编译。这样一来,运行效率会更高。
监控应用更方便:Micrometer 2 + OpenTelemetry
云原生应用想跑稳,“可观测性”(就是能看到应用的运行状态)特别重要。Spring Boot 3 之前就加了Spring 可观测性,这次Spring Boot 4 直接升级到 Micrometer 2,还集成了 OpenTelemetry 的启动器。这样一来,“Trace日志”、“普通日志” 和 “性能指标(metrics)” 就能无缝配合,不用再自己凑一套了。
SSL 证书快过期?现在能清楚看到了
以前看 SSL 证书状态有点麻烦,现在改进了:如果证书链里有快过期的证书,会专门新增一个 expiringChains 条目来显示它们。而且之前的 “WILL_EXPIRE_SOON” 状态没了,快过期的证书会统一标成 “VALID”。
这样一来,团队在生产环境监控 SSL 证书时,能更清楚哪些要过期了,还不会出现没必要的 “误报”,省了不少排查时间。
代码拆得更细了:模块化改造
Spring Boot 4 刚启动开发时,第一个重要目标就是把自己的代码库拆成更 “模块化” 的结构。
以前 Spring Boot 3 里,很多核心模块(比如自动配置、启动器依赖、构建工具这些)都打包在大的 “构件” 里。虽然用着方便,但有时候依赖管理会很乱,类路径扫描也慢,连原生镜像的体积都会变大。
从 Spring Boot 4 开始,团队把 “自动配置” 和 “支持代码” 拆成了更小的模块,每个模块只负责一小块功能。这么改有啥好处?
构建和生成原生镜像更快:GraalVM 的 AOT 处理不用管那些没用的 “提示信息” 和 “元数据” 了。
依赖管理更清爽:像 Micrometer、OpenTelemetry 这些可选的功能,不再跟核心代码打包在一起,而是单独放一个模块,想用就加,不想用也不占地方。
Spring 团队维护起来更轻松:模块和功能一一对应,找问题、改代码都方便,贡献代码的人也更容易上手。
对咱们开发者来说,平时写 pom.xml 或 build.gradle 可能感觉不到变化。只要用 “启动器依赖”(比如 spring-boot-starter-data-jpa),就不用改任何东西。比如要用到 JPA 和 Hibernate,直接在 pom.xml 里加这段依赖就行:
真正的变化在 “底层”:JPA 的自动配置、Hibernate 的集成、还有校验相关的配置,现在都在不同的小模块里了。这样框架在运行时或者 AOT 编译时,能更精准地加载需要的配置,不浪费资源。
新增 @ConfigurationPropertiesSource 注解:跨模块配置更省心
为了让模块化更好用,这次还加了个新注解 @ConfigurationPropertiesSource
。注意哦,它不会改变 “运行时配置属性怎么绑定”,主要是在 “构建阶段” 给 spring-boot-configuration-processor(配置处理器)提个醒。
平时配置处理器给 @ConfigurationProperties
类生成 “元数据” 时,只会从这个类所在的模块里找信息。但在模块化项目里,有时候会用到其他模块的 “嵌套类型” 或者 “基类”,而这些模块的源代码在构建时可能拿不到 —— 这样生成的元数据就会不完整,比如少了属性描述或者默认值。
现在给类加个 @ConfigurationPropertiesSource
注解,就能告诉处理器:“就算这个类没标 @ConfigurationProperties,也得给它生成完整的元数据”。简单说,以后跨模块开发时,再也不用操心元数据缺失的问题了,处理器会自动搞定。
Spring Framework 7
Spring Framework 7 这次既加了很多用户盼了好久的功能,还在测试、API 设计、核心基础功能上做了不少细节优化。一方面让框架更 “现代”,另一方面也帮咱们少写很多重复的模板代码。
测试功能更灵活了
Spring 在测试时会用 “上下文缓存”—— 就是为了平衡 “测试速度” 和 “环境隔离”(避免不同测试互相影响)。关于这个缓存的细节、可能踩的坑,还有怎么解决,大家可以看这篇文章。
这次 Spring Framework 7 加了个 “测试上下文暂停” 的功能。以前跑长时间的集成测试,就算测试闲着没干活,也会占着资源;现在不一样了,Spring 能把缓存里的 “上下文” 暂停,要用的时候再恢复 —— 这样能省内存,跑大量测试的时候速度也会变快。比如处理 JMS 监听器容器、定时任务这些场景,这个功能特别有用。
另外,还新增了一个RestTestClient,用它测试 REST 接口特别方便 —— 用法跟 WebTestClient 差不多,但不用额外装 “响应式基础设施”。
给大家看个例子,就能明白它多简单了:
API 版本控制
很多人一直想要的 “API 版本控制”,这次终于成了框架的一级功能,不用再自己瞎折腾了。
以前咱们要搞 API 版本,得自己想办法:比如在 URL 里加 /v1/,或者自定义请求头、改媒体类型。现在框架原生就支持了,直接给 @GetMapping 加个 version 属性就行,看例子:
也可以在控制器级别统一设版本,比如下面这个 “版本 3” 的控制器:
不过得配置一下 “版本怎么映射到请求上”,有四种方式可选:
路径映射:比如 /api/v1/hello 和 /api/v2/hello
查询参数:比如 /hello?version=1 和 /hello?version=2
请求头:比如请求头里加 X-API-Version: 1 或 2
媒体类型头:比如请求头 Accept: application/json; version=1
下面是 “路径映射” 的配置例子,大家可以参考:
配置完之后,Spring 会自动识别请求里的版本,对应到正确的接口。这样迭代 API 的时候,就不用担心影响老用户了。
@HttpServiceClient:写 HTTP 客户端更简单
还有个好用的功能:声明式 HTTP 客户端。灵感来自 Feign,但更轻量,而且跟 Spring 融得更紧。
以前用 Spring,要调用其他服务的 HTTP 接口,得给 HttpInterface 创建代理,想搞智能点还得自己写代码。比如这个仓库里,就有个自定义的 @HttpClient
注解和 Bean 注册器的例子(Spring Framework 7 还优化了 Bean 注册器,这篇文章有说)。
现在不用自己写了,框架直接给了 @HttpServiceClient
注解,开箱即用。看个例子就懂了:
然后要配置一下 “扫描这个接口” 和 “服务的基础地址”:
配置完之后,这个 ChristmasJoyClient 就能像普通 Bean 一样注入到其他组件里用了,比如下面这个控制器:
弹性能力内置:加个注解就有重试、限流
Spring Retry 虽然在生态里好多年了,但一直像个 “外挂”,不是框架核心功能。这次 Spring Framework 7 直接把 “弹性能力”(比如重试、限流)做成内置的了—— 给 Spring 组件的方法加个注解,就能实现重试逻辑或者并发限制,特别方便。
看个例子,还是刚才的 ChristmasJoyClient,加两个注解就行:
不过要注意:这些注解默认是不生效的,得在某个配置类上加 @EnableResilientMethods
才能启用。
这样一来,不用再依赖 Resilience4j 这类额外库(当然,想集成也能正常用),就能实现弹性功能,省了不少配置功夫。而且还能在运行时验证这些策略有没有生效,不用担心注解白加了。
支持多个 TaskDecorator:异步任务能加多个 “钩子”
以前用 Spring 的时候,想自定义异步任务的执行逻辑,顶多只能在 ThreadPoolTaskExecutor 上挂一个 TaskDecorator。比如把安全上下文(SecurityContext)或者日志里的 MDC 信息传到异步线程里,靠它还能实现。但要是想同时搞好几件事,比如:又传上下文又打日志,就得自己手动写个 “复合装饰器”,特别麻烦。
好在从 Spring Framework 7 开始,咱们能在应用上下文里声明多个 TaskDecorator Bean 了!Spring 会自动把它们串成一个 “装饰链”,按 Bean 定义的顺序或者 @Order 注解标的顺序,一个接一个生效。
举个实际例子,咱们有个异步的事件监听器:
要是想给这个异步任务加个简单日志(记录开始结束),再算个执行时间,不用写复杂代码,直接注册两个 TaskDecorator Bean 就行:
最后日志会输出这样的内容:
这波改进是真省心,不用再写一堆重复的复合装饰器代码了,想给异步任务加多个功能(比如日志、计时、权限校验),直接加 Bean 就行,特别方便。
用 JSpecify 搞定空安全,终于不混乱了
之前 Java 生态里的空值注解随处可见(@Nonnull、@Nullable、@NotNull 等),现在 Spring Framework 7 干脆定了标准:用 JSpecify,示例长这样:
这改进了 IDE 工具和 Kotlin 互操作性,减少了大型代码库中 NullPointerException 的风险。
总结
Spring Boot 4 和 Spring Framework 7 真不是 “小打小闹的更新”,而是 Spring 特意朝着 Java 开发的 “现代化、模块化、云原生” 方向迈的一大步:
有了 API 版本控制和弹性注解,应用既能轻松升级,又能扛住各种异常
靠 JSpecify 的空安全和 Kotlin 支持,运行时出错能少很多。
声明式 HTTP 客户端,服务之间调用不用写一堆请求代码了。
原生镜像支持和可观测性工具加强,往云环境上部署更顺了。
跟所有大版本升级一样,关键是早点拿项目测。尤其是依赖升级和旧 API 替换这两块,早发现问题早解决。不过话说回来,升级后开发效率变高、性能变好、维护也省心,这点麻烦还是值得的。