将Spring移植到GraalVM的团队发布了它的第一个主要版本——Spring Native Beta。与GraalVM的创建者一起,他们设法修复了编译器和Spring中的许多错误。现在这个项目有官方的支持,有自己的发布周期,可以使用。
将代码从JVM移植到二进制的最大障碍是使用java特有特性的问题—反射、类路径处理、动态类加载等。
根据文档,常规JVM和Native实现之间的主要区别如下:
- 整个应用程序的静态分析在构建时执行。
- 未使用的组件将在生成时移除。
- 反射、资源和动态代理只能使用其他配置进行配置。
- 所有组件在构建时都固定在类路径中。
无延迟类加载:可执行文件中提供的所有内容都将在加载时加载到内存中。例如,要使Class.forName(“myClass”)
调用正常工作,您需要在配置文件中包含myClass
。如果在请求动态加载类的配置文件中找不到类,则会抛出ClassNotFoundException
一些代码将在构建时运行以正确链接组件。例如,测试。
在Spring本身中,反射、代理创建和延迟初始化几乎随处可见,因此所有配置都必须小心处理,因此发布它花了一年多的时间。
在研究过程中,创建了一个新组件Spring AOT,负责将代码转换为通用VM可消化格式。
Spring AOT解析代码并使用它创建配置文件,如native-image.properties
、reflection-config.json
、proxy-config.json
或resource-config.json
由于graalvm支持通过静态文件进行初始配置,因此在构建过程中,这些文件被放置在META-INF/native-image
目录中。
每个生成器都有一个不同的插件来激活Spring AOT。对于maven,它是spring-aot-maven-plugin
;对于Gradle,它是spring-aot-gradle-plugin
。要将Gradle-plugin添加到项目中,您只需要一行:
plugins {id ‘org.springframework.experimental.aot’ version ‘0.9.0’}
该插件尝试配置尽可能多的组件,对所有需要改进兼容性的程序组件执行初步转换。
如果它不能做到这一点,您需要自己添加这些数据。这可以通过更正配置文件或使用特别创建的注释手动完成。
例如,对于使用WebClient
实现组件的情况,您可以使用org.springframework.nativex.hint
中的注释来指定要处理的类型:
@TypeHint(types = Data.class, typeNames = “com.example.webclient.Data$SuperHero”)
@SpringBootApplication
public class WebClientApplication { // … }
这里我们指定将序列化数据类,它有一个子类SuperHero
。在构建时,将提前为我们创建一个可以使用此数据类型的客户机。
由于GraalVM不支持使用动态代理,因此创建@ProxyHint
注释是为了支持使用java.lang.reflect.Proxies
。
可以这样应用,例如:
@ProxyHint(types = { org.hibernate.Session.class, org.springframework.orm.jpa.EntityManagerProxy.class })
如果要将任何资源拉入图像,应使用@ResourceHint
注释:
@ResourceHint(patterns = “com/mysql/cj/TlsSettings.properties”)
要指定应在生成或运行时显式初始化哪些类/包,请使用@InitializationHint
注释:
@InitializationHint(types = org.h2.util.Bits.class, initTime = InitializationTime.BUILD)
创建@NativeHint
注释是为了以紧凑的方式将所有这些注释放在一起:
@Repeatable(NativeHints.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeHint
总的来说是这样的,例如:
@NativeHint(
trigger = Driver.class,
options = “ — enable-all-security-services”,
types =
@TypeHint(types = { FailoverConnectionUrl.class // … }),
resources = {
@ResourceHint(patterns = “com/mysql/cj/TlsSettings.properties”),
@ResourceHint(patterns = “com.mysql.cj.LocalizedErrorMessages”, isBundle = true) })
作为一个触发器,我们选择一个类,它在类路径中的存在应该导致构建配置。
所有活动注释在编译时都会被考虑进去,并由Spring AOT插件转换为Graal VM配置。
Spring Native已经包含在发布周期中,您可以直接从start.spring.io获取模板。由于已经实现了对JPA和其他spring组件的支持,您可以立即构建一个简单的CRUD应用程序。如果在构建时需要指定其他Graal VM参数,则可以使用Spring AOT插件中的BP_NATIVE_IMAGE_BUILD_ARGUMENTS
环境变量(如果通过Buildpacks
构建)添加这些参数,或者使用pom.xml中的“<buildArgs>
”配置元素(如果通过native-image-maven-plugin
构建)添加这些参数。
实际上,运行mvn spring boot:build image
或gradle bootBuildImage
命令,镜像将开始构建。值得注意的是,构建器需要超过7GB的内存才能成功构建。在我的机器上,构建和上传镜像只花了不超过5分钟的时间。镜像非常紧凑,只有60 MB。应用程序在0.022秒内启动!这是一个令人难以置信的结果。越来越多的公司正在迁移到K8s,应用程序启动以及使用的资源在当今世界非常重要,这项技术使Spring成为所有类型微服务的第一框架,甚至对于冷启动速度非常重要的FaaS实现也是如此。
原文地址:https://medium.com/geekculture/spring-native-beta-release-a70919da4762
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1999.html
暂无评论