简介
Spring Framework6 和 Spring Boot3 是一个跨越式的升级整个框架支持的最低 JDK 版本直接跨越到 JDK17,无论框架层还是基础设施层都做了巨大的改变,Spring 6.0 新框架具体做了哪些功能的升级与改进,是否有必要升级与使用呢?可以继续看一看。
下面可以先看下翻译自 Spring 官方社区一个宣导博客
尊敬的 Spring 社区:我很高兴地宣布,现在 MavenCentral 已经可以提供 SpringFramework6.0.0 了!这是 2023 年及以后新一代框架的开始,包括 OpenJDK 和 Java 生态系统中当前和未来的创新。同时,我们将其精心设计为从 Spring Framework 5.3.x 直接升级到现代运行时环境。作为核心框架的一个主要修订,Spring framework 6.0 附带了 Java 17+基线和 Jakarta EE 9+(在 Jakarta 命名空间中),重点是最近发布的 Jakarta EE10 API,如 Servlet 6.0 和 JPA 3.1。这提供了对最新 web 容器(如 Tomcat 10.1)和最新持久性提供程序(如 Hibernate ORM 6.1)的访问。不要拘泥于 JavaEE8,跳到 jakarta 命名空间,最好直接跳到 JakartaEE10 级别!即将发布的 SpringBoot3.0.0 版本为您提供了相应的托管依赖项。基础架构方面,6.0 为提前转换和相应的 AOT 处理支持 Spring 应用程序上下文提供了基础。这使得 Spring Boot 3 能够为 GraalVM 本地映像提供一流的支持。您还可以探索 Project Loom 的虚拟线程和 Spring 应用程序-请参阅“拥抱虚拟线程”-并深入了解 Project CRaC 的检查点恢复方法,以加快 JVM 启动速度,这两个功能目前都在预览中,但预计将成为基于 SpringFramework6.x 的应用程序的一流功能。Spring Framework 6.0 中还有许多其他特性和改进,例如 HTTP 接口客户端、对 RFC 7807 问题细节的支持,以及 HTTP 客户端基于千分尺的可观察性。请查看我们的“新增内容”页面,了解全面概述,并尽早尝试 6.0.0!2022 年 11 月 16 日 Cheers,Juergen
如果对原文感兴趣也可以直接访问官方原文spring.io/blog/2022/1…
通过官方宣导内容可以看到 Spring 做了很多基础设施方面的改进:
- 支持 Java 17+基线和 Jakarta EE 9+
- 对新一代容器 Tomcat 10.1 的支持
- 为 GraalVM 本地映像提供一流的支持
- 拥抱虚拟线程
- 其他功能优化等等
对于主要用于 CRUD 的我们可能仅仅因为这些功能的改变还不值得我们全面升级。下面就整体从 Spring 支持的历史版本来看下。
更新记录
支持的版本
- 6.0.x 是截至 2022 年 11 月的当前功能分支和主要生产线。新一代需要 JDK 17 基线。
- 5.3.x 是第五代的最终功能分支,也是最新的生产线(截至 2020 年 10 月的 GA),在 JDK 8、JDK 11 和 JDK 17 上提供了长期支持。
- 5.2.x 是之前的生产线(截至 2019 年 9 月的 GA),将得到积极支持,直至 2021 年底。
- 5.1.x 和 5.0.x 不再受到积极支持,截至 2020 年 12 月已被 5.2.x 和 5.3.x 取代。
- 4.3.x 于 2020 年 12 月 31 日达到了正式的 EOL(寿命终止)。该线路没有计划进一步的维护和安全补丁。
- 3.2.x 于 2016 年 12 月 31 日达到其正式 EOL(使用寿命终止)。该线路未计划进一步的维护和安全补丁。
此时,官方建议尽可能从 MavenCentral 升级到最新的 SpringFramework6.0.x 版本。
相关 JDK 版本范围
根据官方文档的说明 Spring 与 JDK 的兼容版本如下列表所示:
- Spring Framework 6.0.x: JDK 17-21 (expected)
- Spring Framework 5.3.x: JDK 8-19 (expected)
- Spring Framework 5.2.x: JDK 8-15
- Spring Framework 5.1.x: JDK 8-12
- Spring Framework 5.0.x: JDK 8-10
- Spring Framework 4.3.x: JDK 6-8
可以看到 5.3.x 及以下的版本都是兼容 JDK8 的, 如果短期内还没有完全计划升级 JDK17 可以使用 5.3.x 的版本不仅仅兼容 JDK8 也会兼容 11 和 17 这两个稳定版本。
Spring Framework 6.x 的新增了哪些功能?
有了历史背景接下来直接进去主题,Spring Framework 6.x 的新增了哪些功能?
JDK 17+和 Jakarta EE 9+基线
- 整个框架代码库基于 Java17 源代码级别的,已经开始不支持 JDK8 了,如果未来继续用 Spring 这个早晚得升级。
- Servlet、JPA 等从 javax 迁移到 jakarta 命名空间。
- 与 jakarta EE 9 以及 jakarta EE 10 API 的运行时兼容性。
- 与最新的 web 服务器兼容:Tomcat 10.1、Jetty 11、Undertow 2.3。
- 与虚拟线程的早期兼容性(在 JDK 19 的预览版中)。
核心修订
- 升级至 ASM 9.4 和 Kotlin 1.7。
- 完成 CGLIB 分叉,支持捕获 CGLIB 生成的类。
- AOT 的全面基础。
- 对 GraalVM 本机映像的一流支持(请参阅相关的 SpringBoot3 博客文章)。
核心容器
- 默认情况下,没有 java.beans.Invector 的基本 bean 属性确定。
- GenericApplicationContext 中的 AOT 处理支持(refreshForAotProcessing)。
- 基于预解析构造函数和工厂方法的 Bean 定义转换。
- 支持 AOP 代理和配置类的早期代理类确定。
- PathMatchingResourcePatternResolver 使用 NIO 和模块路径 API 进行扫描,分别支持 GraalVM 本地映像和 Java 模块路径中的类路径扫描。
- DefaultFormattingConversionService 支持基于 ISO 的默认 java.time 类型解析。
数据访问和事务
- 支持预先确定 JPA 管理的类型(用于包含在 AOT 处理中)。
- JPA 支持 Hibernate ORM 6.1(保持与 Hibernate ORM5.6 的兼容性)。
- 升级至 R2DBC 1.0(包括 R2DBC 事务定义)。
- 拆除 JCA CCI 支架。
Spring 消息
- 基于 @RSocketExchange 服务接口的 RSocket 接口客户端。
- 基于 Netty 5 αlpha 的反应模式的早期支持。
- 支持 Jakarta WebSocket 2.1 及其标准 WebSocket 协议升级机制。
常规 Web 修订
- 基于 @HttpExchange 服务接口的 HTTP 接口客户端。
- 支持 RFC 7807 问题详细信息。
- 统一的 HTTP 状态代码处理。
- 支持 Jackson 2.14。
- 与 Servlet 6.0 保持一致(同时保持与 Servlet 5.0 的运行时兼容性)。
Spring MVC
- 默认情况下使用的 PathPatternParser(具有选择 PathMatcher 的功能)。
- 删除过时的文件和 FreeMarker JSP 支持。
Spring WebFlux
- 新的 PartEvent API 用于流式传输多部分表单上传(在客户端和服务器上)。
- 新建 ResponseEntityExceptionHandler 以自定义 WebFlux 异常并呈现 RFC 7807 错误响应。
- 非流媒体类型的通量返回值(写入前不再收集到列表)。
- 基于 Netty 5 的反应模式的早期支持。
- JDK HttpClient 与 WebClient 集成。
可观察性
- 在 Spring 框架的几个部分中使用 micrometer 观测的可观测性仪器。springweb 模块现在需要 io.micrometer:micrometer observation:1.10+作为编译依赖项。
- RestTemplate 和 WebClient 被检测以生成 HTTP 客户端请求观察结果。
- 可以使用新的 org.springframework.web.filter.ServerHttpObservationFilter 为 HTTP 服务器观测检测 Spring MVC。
- 可以使用新的 org.springframework.web.filter.active.ServerHttpObservationFilter 为 HTTP 服务器观测检测 SpringWebFlux。
- 与控制器方法的 Flux 和 Mono 返回值的 micrometer 上下文传播集成。
测试
- 支持在 JVM 上或 GraalVM 本机映像中测试 AOT 处理的应用程序上下文。
- 与 HtmlUnit 2.64+请求参数处理集成。
- Servlet 模拟(MockHttpServletRequest、MockHttpSession)现在基于 Servlet API 6.0。
总结
整体来看 Spring6 做了很多升级,接下来就总结几个比较重要的点:
JDK17
最低 JDK 支持版本改为 JDK17,可能大家用惯了 JDK8,这个免费又稳定支持的版本,其实 JDK 社区已经发布了支持 G1 垃圾回收器的稳定版本 JDK11,JDK11 就像是一个过渡版本一样,和 JDK8 社区提供支持的时间差不多,另外升级 JDK11 又需要做大量的兼容性测试才能正式使用,倒不如直接使用 JDK17 来的痛快。
关于 JDK17 的相关文档如下:
下载地址:www.oracle.com/java/techno…
文档地址:docs.oracle.com/en/java/jav…
迁移指南:docs.oracle.com/en/java/jav…
JDK17 引入了 ZGC,在 GC 延迟方面,JDK 17 的提升更为明显。根据网上有人压测的数据,在 Parallel 中 JDK 17 对比 JDK 8 和 JDK 11 提升 40%;在 G1 中,JDK 11 对比 JDK 8 提升 26%,**JDK 17 对比 JDK 8 提升接近 60%!**ZGC 中 JDK 17 对比 JDK 11 提升超过 40%。如果对 GC 延迟有更高的要求的用户可以考虑尽早体验 JDK17。
JDK 17 是一个 Oracle 官宣可以免费商用的 LTS 版本,所谓 LTS,是 Long Term Support,也就是官方保证会长期支持的版本,根据官方数据最多可以支持到 2029 年 9 月份。
AOT
可能很多人听说过 JIT,第一次听说 AOT 这个名词,下面就来解释一下:
这两种编译方式的主要区别在于是否在“运行时”进行编译,JIT,即 Just-in-time,动态(即时)编译,边运行边编译;
AOT,Ahead Of Time,指运行前编译,是两种程序的编译方式。
有两种编译 Java 应用程序的方法:使用即时编译 (JIT) 或提前编译 (AOT)。第一种是默认模式,Java Hotspot 虚拟机使用它在运行时将字节码转换为机器码。后者由新颖的 GraalVM 编译器支持,并允许在构建时将字节码直接静态编译为机器码。
JIT (Just-In-Time - 实时编译)
在程序运行时,根据算法计算出热点代码,然后进行 JIT 实时编译,这种方式吞吐量高,有运行时性能加成,可以跑得更快,并可以做到动态生成代码等,但是相对启动速度较慢,并需要一定时间和调用频率才能触发 JIT 的分层机制。JIT 缺点就是编译需要占用运行时资源,会导致进程卡顿。
AOT (Ahead-Of-Time - 预先编译)
AOT 编译能直接将源代码转化为机器码,内存占用低,启动速度快,可以无需 runtime 运行,直接将 runtime 静态链接至最终的程序中,但是无运行时性能加成,不能根据程序运行情况做进一步的优化,AOT 缺点就是在程序运行前编译会使程序安装的时间增加。
现在正处于云原生,降本增效的时代,Java 相比于 Go、Rust 等其他编程语言非常大的弊端就是启动编译和启动进程非常慢,这对于根据实时计算资源,弹性扩缩容的云原生技术相冲突,Spring6 借助 AOT 技术在运行时内存占用低,启动速度快,逐渐的来满足 Java 在云原生时代的需求,对于大规模使用 Java 应用的商业公司可以考虑尽早调研使用 JDK17,通过云原生技术为公司实现降本增效。
关于 AOT 再简单介绍一下 Native Image 这个名词
Native Image 是一项创新技术,可将 Java 代码编译成独立的本机可执行文件或本机共享库。在构建本机可执行文件期间处理的 Java 字节码包括所有应用程序类、依赖项、第三方依赖库和任何所需的 JDK 类。生成的自包含本机可执行文件特定于不需要 JVM 的每个单独的操作系统和机器体系结构。
Graalvm
前面说到了 Spring6 支持的 AOT 技术,这个 Graalvm 就是底层的支持,Spring 也对 GraalVM 本机映像提供了一流的支持。
GraalVM 是一种高性能 JDK,旨在加速用 Java 和其他 JVM 语言编写的应用程序的执行,同时还为 JavaScript、Python 和许多其他流行语言提供运行时。 GraalVM 提供两种运行 Java 应用程序的方法:在 HotSpot JVM 上使用 Graal 即时 (JIT) 编译器或作为提前 (AOT) 编译的本机可执行文件。 GraalVM 的多语言能力使得在单个应用程序中混合多种编程语言成为可能,同时消除了外语调用成本。
GraalVM 向 HotSpot Java 虚拟机添加了一个用 Java 编写的高级即时 (JIT) 优化编译器。
Graalvm 架构如下图所示:
GraalVM 具有以下特性:
- 高性能应用 Graal,一种高级优化编译器,它生成更快、更精简的代码,需要更少的计算资源
- AOT 本机图像编译提前将 Java 应用程序编译为本机二进制文件,立即启动,无需预热即可实现最高性能
- Polyglot 编程在单个应用程序中利用流行语言的最佳功能和库,无需额外开销
- 高级工具在 Java 和多种语言中调试、监视、分析和优化资源消耗
总的来说对云原生的要求不算高短期内可以继续使用 2.7.X 的版本和 JDK8,不过 Spring 官方已经对 Spring6 进行了正式版发布,后续有足够精力支持的时候可以尝试在 Spring6 和 JDK17 上进行项目验证尽早升级到这些版本上进行试点比较好。
如果对此文感兴趣可以关注微信公众号 《中间件源码》 交流。