当前位置: 首页 > news >正文

Spring 6.0 新特性

文章目录

  • Spring的发展历史
  • AOT
  • GraalVM
  • SpringBoot实战AOT
  • RuntimeHints
    • 案例分析
    • RuntimeHintsRegistrar
  • SpringBoot中AOT核心代码

Spring的发展历史

image.png

AOT

Spring 6.0的新特性Ahead of Time(AOT)编译是一种技术,可以提前将Spring应用程序编译成原生镜像,从而加快启动速度并降低内存消耗。AOT编译与传统的即时编译(JIT)相比,最大的优点是可以在程序运行前进行预编译,避免在程序运行时进行编译和内存消耗。

JIT(Just-in-time) 动态编译,即时编译,也就是边运行边编译,在程序运行时,动态生成代码,启动比较慢,编译时需要占用运行时的资源。

AOT,Ahead Of Time 指的是运行前编译,预先编译,AOT 编译能直接将源代码转化为机器码,内存占用低,启动速度快,可以无需 runtime 运行,直接将 runtime 静态链接至最终的程序中,但是无运行时性能加成,不能根据程序运行情况做进一步的优化,AOT 缺点就是在程序运行前编译会使程序安装的时间增加。

简单来讲:JIT即时编译的是在程序的运行过程中,将字节码转换为可在硬件上直接运行的机器码,并部署至托管环境中的过程。而 AOT 编译指的则是,在程序运行之前,便将字节码转换为机器码的过程。

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 具有以下特性:

  1. 一种高级优化编译器,它生成更快、更精简的代码,需要更少的计算资源
  2. AOT 本机图像编译提前将 Java 应用程序编译为本机二进制文件,立即启动,无需预热即可实现最高性能
  3. Polyglot 编程在单个应用程序中利用流行语言的最佳功能和库,无需额外开销
  4. 高级工具在 Java 和多种语言中调试、监视、分析和优化资源消耗

SpringBoot实战AOT

在SpringBoot项目中通过AOT来提前编译我们的项目。

新建一个Maven项目。添加相关的依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.2</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

添加相关的SpringBoot插件

    <build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

编写一点简单的代码测试,打开 x64 Native Tools Command Prompt for VS 2019 ,切换到工程目录下

image.png

执行 mvn -Pnative native:compile 进行编译,编译成功就会在target目录下生成 EXE 文件,后续执行该文件就可以。

image.png
双击执行exe文件,会发现速度快很多

RuntimeHints

与常规 JVM 运行时相比,将应用程序作为本机映像运行需要额外的信息。例如,GraalVM 需要提前知道组件是否使用反射。同样,除非明确指定,否则类路径资源不会在本机映像中提供。因此,如果应用程序需要加载资源,则必须从相应的 GraalVM 原生图像配置文件中引用它。

APIRuntimeHints在运行时收集反射、资源加载、序列化和 JDK 代理的需求。

案例分析

声明个普通的实体类型

public class UserEntity {public String hello(){return "hello ...";}
}

在控制器中通过反射来操作处理

    @GetMapping("/hello")public String hello(){String res = "hello";try {Method hello = UserEntity.class.getMethod("hello");res =  (String)hello.invoke(UserEntity.class.newInstance(),null);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);}return res;}

通过命令编译为 exe 文件

image.png

运行exe文件后,通过浏览器发起请求。

在HelloController中。通过反射的方式使用到了UserEntity的无参构造方法。如果不做任何处理。那么打成二进制可执行文件后是执行不了的,可以通过 Runtime Hints 机制来处理。

RuntimeHintsRegistrar

官网提供的解决方案,自定义一个RuntimeHintsRegistrar接口的实现类,然后把该实现类注入到Spring中

image.png

@RestController
@ImportRuntimeHints(HelloController.UserEntityRuntimeHints.class)
public class HelloController {@GetMapping("/hello")public String hello(){String res = "hello";try {Method hello = UserEntity.class.getMethod("hello");res =  (String)hello.invoke(UserEntity.class.newInstance(),null);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);}return res;}static class UserEntityRuntimeHints implements RuntimeHintsRegistrar{@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {try {hints.reflection().registerConstructor(UserEntity.class.getConstructor(), ExecutableMode.INVOKE);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}
}

SpringBoot中AOT核心代码

执行 mvn -Pnative native:compile时会执行GraalVM中的相关指令。最终会调用SpringApplicationAotProcessor中的main 方法来完成相关提前编译操作。

	public static void main(String[] args) throws Exception {int requiredArgs = 6; // 调用main方法接收的有6个参数Assert.isTrue(args.length >= requiredArgs, () -> "Usage: " + SpringApplicationAotProcessor.class.getName()+ " <applicationName> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId> <originalArgs...>");// 获取SpringBoot项目的入口classClass<?> application = Class.forName(args[0]);// 通过传递过来的参数完成相关生成目录的配置Settings settings = Settings.builder().sourceOutput(Paths.get(args[1])).resourceOutput(Paths.get(args[2])).classOutput(Paths.get(args[3])).groupId((StringUtils.hasText(args[4])) ? args[4] : "unspecified").artifactId(args[5]).build();String[] applicationArgs = (args.length > requiredArgs) ? Arrays.copyOfRange(args, requiredArgs, args.length): new String[0];// 执行 process 方法new SpringApplicationAotProcessor(application, settings, applicationArgs).process();}
	public final T process() {try {// 设置状态System.setProperty(AOT_PROCESSING, "true");return doProcess(); // 处理的核心方法}finally {System.clearProperty(AOT_PROCESSING);}}
 	@Overrideprotected ClassName doProcess() {deleteExistingOutput(); // 删除已经存在的目录// 启动SpringBoot服务  但是不会做扫描beanGenericApplicationContext applicationContext = prepareApplicationContext(getApplicationClass());return performAotProcessing(applicationContext);}
	@Overrideprotected GenericApplicationContext prepareApplicationContext(Class<?> application) {return new AotProcessorHook(application).run(() -> {Method mainMethod = application.getMethod("main", String[].class);return ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });});}

此时会执行启动类中的main方法来启动SpringBoot

image.png

在启动中创建Spring上下文对象时会做如下的处理

	private ConfigurableApplicationContext createContext() {if (!AotDetector.useGeneratedArtifacts()) {return new AnnotationConfigServletWebServerApplicationContext();}return new ServletWebServerApplicationContext();}

如果没有使用AOT,那么就会创建AnnotationConfigServletWebServerApplicationContext,它里面会添ConfigurationClassPostProcessor,从而会解析配置类。而如果使用了AOT,则会创建ServletWebServerApplicationContext,它就是一个空容器,它里面没有ConfigurationClassPostProcessor,所以后续不会触发扫描了。

相关文章:

Spring 6.0 新特性

文章目录 Spring的发展历史AOTGraalVMSpringBoot实战AOTRuntimeHints案例分析RuntimeHintsRegistrar SpringBoot中AOT核心代码 Spring的发展历史 AOT Spring 6.0的新特性Ahead of Time&#xff08;AOT&#xff09;编译是一种技术&#xff0c;可以提前将Spring应用程序编译成原…...

计算机竞赛 深度学习+opencv+python实现昆虫识别 -图像识别 昆虫识别

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数&#xff1a;2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 4 MobileNetV2网络5 损失函数softmax 交叉熵5.1 softmax函数5.2 交叉熵损失函数 6 优化器SGD7 学…...

软件过程能力成熟度评估——CSMM认证

CSMM认证又称为“软件过程能力过程成熟度评估”&#xff0c;由中国电子技术标准化研究院联合五十余家产学研用相关方结合我国实际&#xff0c;自主制定的团体标准&#xff0c;于2021年6月8号发布&#xff0c;目的是为了帮助国内软件企业对自身的软件能力进行评估和判断&#xf…...

学内核之二十一:系统调用栈结构分析

目录 一 构建分析环境 二 栈的位置 三 栈开头8字节 四 寄存器环境 五 R4和R5 六 如何确定系统调用的具体函数 一 构建分析环境 为了分析方便&#xff0c;做了如下测试环境&#xff1a; 内核实现一个简单的创建字符设备的驱动 应用层实现一个c程序&#xff0c;操作为打开内…...

互联网3.0 数字原生——数物虚实多维细粒度泛在融合

随着计算机、宽带网、通信技术的飞速发展&#xff0c;互联网技术和软硬件系统也不断演进&#xff0c;催生了一场前所未有的数字化革命。从Web1.0到Web3.0&#xff0c;以及虚拟现实、人工智能和数字孪生等领域的崛起&#xff0c;每一步都勾画出了一个崭新的数字未来&#xff0c;…...

实现AIGC更好的数据存力,这家科技巨头为我们指明了方向

存力即数据存储能力 蕴藏着巨大的发展机会 【全球存储观察 &#xff5c; 热点关注】 2023年&#xff0c;全球被ChatGPT的热潮席卷&#xff0c;拥抱AIGC的创新赛道成为众多企业的新选择。 全球存储观察分析指出&#xff0c;影响AIGC发展的三大因素也日益凸显&#xff0c;即算…...

企业如何在抖音上搞到TOB潜在精准客户流量?

我们都知道&#xff0c;现在互联网上流量都被集中了几个大的平台里。而抖音&#xff0c;一定是绕不开那个&#xff01;图片在公众号&#xff1a;白杨SEO上去看。 抖音&#xff0c;在很多人的传统印象里&#xff0c;还只是一个娱乐短视频APP&#xff0c;用来打发时间而已。事实…...

JeecgBoot v3.5.5 版本发布,性能大升级版本—开源免费的低代码开发平台

项目介绍 JeecgBoot是一款企业级的低代码平台&#xff01;前后端分离架构 SpringBoot2.x&#xff0c;SpringCloud&#xff0c;Ant Design&Vue3&#xff0c;Mybatis-plus&#xff0c;Shiro&#xff0c;JWT 支持微服务。强大的代码生成器让前后端代码一键生成! JeecgBoot引领…...

与树上边权、连通块、二分块相关的问题(抓住各连通块之间的联系,考虑增量):CF444E

https://www.luogu.com.cn/problem/CF444E 首先肯定二分 然后是棵树&#xff0c;所以考虑按顺序枚举边权 然后肯定会有连通块和并查集 考虑现在场上有多个连通块&#xff0c;我们只保留大于 m i d mid mid 的边 则每个连通块都必须往外连边 一个很朴素的思路是判定每个连…...

解决VSCode下载速度很慢

这是VSCode的官网&#xff1a; Visual Studio Code - Code Editing. Redefined 按照官网的下载链接&#xff0c;速度实在是感人&#xff01; 解决办法也很简单&#xff0c;把链接换为CDN加速的链接 把下载链接中的az764295.vo.msecnd.net 替换为&#x1f449; vscode.cdn.azu…...

悬赏算命测算源码可以用二维码收款 可以直接拿来运营

首发悬赏算命测算源码可以用二维码收款 可以直接拿来运营吸金&#xff01;用户可以通过发布悬赏赏金算命&#xff0c;也可以通过升级发布测算任务来吸金 测试环境&#xff1a;php5.6apache2.4mysq5.6 安装教程&#xff1a; 测试环境&#xff1a;php5.6apache2.4mysq5.6 安装&…...

在Linux中安装nginx-1.20.1+php-7.4.28(增加扩展)

NginxPHP安装在公网IP为x.x.x.x的服务器上 需要下载安装的软件版本&#xff1a;nginx-1.20.1php-7.4.28 需要增加的PHP扩展如下&#xff1a; 在编译安装php-7.4.28时加上的pcntl&#xff1b; 单独下载安装的Wxwork_finance_sdk&#xff1b;&#xff08;在编译安装php-7.4.2…...

使用vue-cli搭建SPA项目

一.SPA项目的构建 前提 nodeJS环境已经搭建完毕 node -v npm -v 什么是SPA项目 SPA&#xff08;Single Page Application&#xff09;项目是一种使用单页面架构的Web应用项目。在SPA项目中&#xff0c;整个应用程序只有一个HTML页面&#xff0c;通过动态加载数据和更新DOM来实…...

PLC串口通讯和通讯接口知识汇总

在使用PLC的时候会接触到很多的通讯协议以及通讯接口&#xff0c;最基本的PLC串口通讯和基本的通讯接口你都了解吗&#xff1f; 一、什么是串口通讯&#xff1f; 串口是一种接口标准&#xff0c;是计算机上一种非常通用设备通信的协议。它规定了接口的电气标准&#xff0c;没…...

Vue基础入门---详细简介

一&#xff0c;对Vue的概念 1.1 什么是Vue &#xff1f; 一种流行的JavaScript前端框架&#xff0c;用于构建交互式的Web应用程序。它以简洁、灵活和高效的特性而受到广泛欢迎。Vue采用了一种响应式的数据绑定机制&#xff0c;使得数据的变化能够自动更新相关的DOM元素&#x…...

Qt重写QTreeWidget实现拖拽

介绍 此文章记录QTreeWidget的重写进度&#xff0c;暂时停滞使用&#xff0c;重写了QTreeWidget的拖拽功能&#xff0c;和绘制功能&#xff0c;自定义了数据结构&#xff0c;增加复制&#xff0c;粘贴&#xff0c;删除&#xff0c;准备实现动态刷新数据支持千万数据动态刷新&a…...

【Spring Boot】拦截器学习笔记

一、普通拦截器 1&#xff0c;新建类MyWebConfig实现WebMvcConfigurer&#xff0c;实现addInterceptors方法 Overridepublic void addInterceptors(InterceptorRegistry registry) {registry// 不拦截哪些请求.excludePathPatterns("/login")// 拦截哪些请求.addPat…...

云可观测性:提升云环境中应用程序可靠性

随着云计算的兴起和广泛应用&#xff0c;越来越多的企业将其应用程序和服务迁移到云环境中。在这个高度动态的环境中&#xff0c;确保应用程序的可靠性和可管理性成为了一个迫切的需求。云可观测性作为一种解决方案&#xff0c;针对这一需求提供了有效的方法和工具。本文将介绍…...

免杀对抗-java语言-shellcode免杀-源码修改+打包exe

JAVA-ShellCode免杀-源码修改&打包EXE Shellcode-生成/上线 1.msf生成shellcode 命令&#xff1a;msfvenom -p java/meterpreter/reverse_tcp LHOSTx.x.x.x LPORTxxxx -f jar -o msf.jar 2.msf设置监听 3.执行msf生成的shellcode jar包&#xff0c;成功上线 命令&#xff1…...

抖音、知乎、小红书的流量算法

目前我国网民规模已超过10亿&#xff0c;在这互联网时代&#xff0c;更是流量为王。各个平台里的每个视频、每张图片&#xff0c;背后都有着算法的身影&#xff0c;支配着所有人的流量。作为内容创作者及运营者来说&#xff0c;除了制作高质量的内容以外&#xff0c;也需要掌握…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...

RabbitMQ 各类交换机

为什么要用交换机&#xff1f; 交换机用来路由消息。如果直发队列&#xff0c;这个消息就被处理消失了&#xff0c;那别的队列也需要这个消息怎么办&#xff1f;那就要用到交换机 交换机类型 1&#xff0c;fanout&#xff1a;广播 特点 广播所有消息​​&#xff1a;将消息…...