简介
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
如果对原文感兴趣也可以直接访问官方原文https://spring.io/blog/2022/11/16/spring-framework-6-0-goes-ga
通过官方宣导内容可以看到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的相关文档如下:
下载地址:https://www.oracle.com/java/technologies/downloads/#jdk17-mac
文档地址:https://docs.oracle.com/en/java/javase/17/index.html
迁移指南:https://docs.oracle.com/en/java/javase/17/migrate/getting-started.html
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上进行项目验证尽早升级到这些版本上进行试点比较好。
如果对此文感兴趣可以关注微信公众号《中间件源码》交流。