领先一步
VMware 提供培训和认证,助您加速进步。
了解更多经过一年半的工作,我很高兴地宣布,我们正在发布 Spring Native 的 Beta 版本,并且它已在 start.spring.io 上可用!
实际上,这意味着除了 Spring 自创建以来一直支持的常规 Java 虚拟机之外,我们还增加了对使用 GraalVM 将 Spring 应用程序编译为 原生镜像 的 Beta 支持,以提供一种部署 Spring 应用程序的新方法。支持 Java 和 Kotlin。
这些原生 Spring 应用程序可以作为独立的可执行文件进行部署(无需安装 JVM),并提供有趣的特性,包括几乎即时启动(通常 < 100 毫秒)、即时峰值性能和更低的内存消耗,但代价是构建时间更长,运行时优化比 JVM 少。

通过简单的 mvn spring-boot:build-image 或 gradle bootBuildImage 命令,您可以生成一个优化的容器镜像,其中包含一个最小的操作系统层和一个小型原生可执行文件,该文件仅包含 JDK、Spring 和您应用程序中使用的依赖项所需的位。例如,下面是一个包含 Spring Boot、Spring MVC、Jackson、Tomcat、JDK 和应用程序的 50MB 可执行文件的最小容器镜像。

您的 Spring 应用程序有很多可以用原生方式部署的场景
结合 Spring Cloud Function 的 Serverless
更经济、更可持续地托管您的 Spring 微服务
非常适合 Kubernetes 平台,例如 VMware Tanzu
希望创建最佳的容器镜像来打包您的 Spring 应用程序和服务
我相信出色的 Spring 社区会发现更多,例如 Piotr Mińkowski 关于如何使用 Spring Boot 和 GraalVM 在 Knative 上构建原生微服务的精彩教程。
Spring Native Beta 是 Spring 团队及其项目组合(Spring Framework、Spring Boot、Spring Data、Spring Security、Spring Cloud 和 Spring Initializr)广泛协作的结果。观看此视频,了解 Spring 团队如何构建 Spring Native Beta 以及它提供的功能,包括对全新 start.spring.io 支持的演示。
我们的原生工作范围比 Spring 更广,因为原生涉及到更广泛的 JVM 生态系统,因此我们一直与 GraalVM 团队合作,以提高原生镜像的兼容性和占用空间。以下是 GraalVM 团队的 Vojin Jovanovic 的引述:
“与 Spring 团队合作构建原生 JVM 生态系统是一件非常令人高兴的事情:他们深厚的技术知识,以及对社区的敏锐洞察力,总是能带来最佳的解决方案。最新的 Spring Native 版本及其在 JVM 生态系统中的众多应用,为原生编译的广泛采用铺平了道路。”
随着 Spring Native 从 Alpha 版升级到 Beta 版,我认为有必要明确我们提供的支持范围。
Alpha 是第一步,我们在此阶段进行了大量实验,并在大量具有破坏性更改的样本中优化了 Spring Native(以前称为 Spring GraalVM Native)的架构、兼容性和占用空间。我们还报告了大量问题,GraalVM 团队已修复这些问题,以缩小 JVM 和原生镜像在 Spring 应用程序上的差距。
虽然它仍被视为实验性的,但 Beta 版意味着 Spring 现在为Spring 生态系统的子集提供原生支持。如果您的项目使用了受支持的依赖项,您可以尝试使用它们,如果出现问题,可以报告 bug 或贡献 pull requests。对于最新的 Spring Boot 2.x 次要版本的每个补丁版本,都会发布一个新的 Spring Native 版本。Spring Native 0.9.0 支持 Spring Boot 2.4.3,Spring Native 0.9.1 将支持 Spring Boot 2.4.4,依此类推。会有破坏性更改,但我们会记录迁移路径。文档质量已达到新水平:参考文档可作为html 单页或pdf 提供,并且我们发布了原生提示公共 API 的 Javadoc。
Stéphane Nicoll 在 start.spring.io 和相关的 IDE 集成中引入了对 Spring Native 的支持,因此从今天起,这可能是探索如何使用 Spring 构建原生应用程序的最简单方法。

添加 Spring Native 依赖项将自动为您的 Maven 或 Gradle 项目配置必需的依赖项和插件以支持原生。应用程序代码本身保持不变。
请务必检查生成的 HELP.md 文件,其中包含有用的链接和文档,同时还会指示您是否选择了某些在原生环境中不受支持的依赖项。
原生与 JVM 不同:类路径在构建时固定,需要进行配置(例如,用于反射或资源),没有类懒加载(可执行文件中包含的所有内容都在启动时加载到内存中),并且某些代码可以在构建时调用。
为了充分利用这些特性,并使 Spring 应用程序在原生环境中具有最大的兼容性和最小的占用空间,Brian Clozel 在此版本中引入了 Spring 提前编译(AOT)Maven 和 Gradle 插件,它们会对您的应用程序执行提前转换。
第一种转换旨在基于由出色的 Andy Clement 设计和实现的推理引擎生成 GraalVM 原生配置(反射、资源、代理、native-image 选项),该引擎理解 Spring 编程模型和基础架构。例如,对于每个用 @Controller 标注的类,都会在生成的 reflect-config.json 文件中添加一个条目。
某些原生配置无法推断,对于这些情况,我们引入了原生提示注解(更多详细信息请参阅Javadoc),这使得 Spring Native 能够以比常规基于 JSON 的原生镜像配置更易于维护、类型安全和灵活的方式来支持原生配置。例如,Spring Native 的 MySQL 驱动程序支持提供提示,这些提示允许在原生镜像的 reflect-config.json、resource-config.json 和 native-image.properties 中生成正确的条目,如下所示:
@NativeHint(
trigger = Driver.class,
options = "--enable-all-security-services",
types = @TypeHint(types = {
FailoverConnectionUrl.class,
FailoverDnsSrvConnectionUrl.class,
// ...
}), resources = {
@ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),
@ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",
isBundle = true)
})
public class MySqlHints implements NativeConfiguration {}
NativeConfiguration 和其他动态配置机制允许生成更强大、更动态的配置,但请注意,它们 API 在未来版本中将发生很大变化。
Spring 开发人员还可以直接在他们的 @Configuration 或 @SpringBootApplication 类上使用特定于应用程序的原生提示进行注解,例如,通过 RestTemplate 或 WebClient 等程序化 API 将 Book 类序列化为 JSON。
@TypeHint(types = Book.class)
@SpringBootApplication
public class WebClientApplication {
// ...
}
在与提前编译转换系统一起工作时,最后一个也是可能最强大的机制是能够利用 Spring Boot 部署模型结合 GraalVM 原生镜像特性引入的封闭世界假设,自动生成原生优化的代码(源代码和字节码)。这样做的目标是限制所需额外原生配置的数量,以提高兼容性,方法是使用原生镜像编译器开箱即用的代码结构,并通过减少反射、资源或代理所需的配置量来降低占用空间。一个具体的例子是,提前编译各种 spring.factories(Spring Boot 后面的扩展机制)到一个优化的程序化版本,该版本不需要反射,并且在您的应用程序上下文中过滤掉不必要的条目。
这只是 Spring AOT 的一个开始,我们打算添加更强大的转换,例如将@Configuration 转换为函数式配置,通过提前分析来替换运行时反射,该分析将自动生成使用 lambda 和方法引用等程序化构造的配置类。这将使 GraalVM 原生镜像编译器能够开箱即用地理解 Spring 配置,而无需任何反射配置或 *.class 资源。
要记住的一个关键点是,在使用 Spring Native 时,此 AOT 生成的代码默认也会在 JVM 上使用,以便您可以使用 JVM 提供的简短反馈循环,以及调试器和所有常规工具来练习“原生友好型代码路径”。
虽然 Spring AOT 转换目前主要由原生需求驱动,但其中许多并非原生特有,并且有些可能为在 JVM 上运行 Spring Boot 应用程序提供优化。对于此类主题,一如既往,重要的是基于数据做出决策,因此我们将衡量效率和性能来驱动我们的决策。
我们可能会改进 IDE 集成,但目前请务必阅读相关文档,了解在 IDE 中运行应用程序之前更新生成源代码的潜在手动配置步骤。
Spring 的原生战略有两个主要支柱。第一个是适应 Spring 基础架构以适应原生环境,而无需对数百万现有的 Spring Boot 应用程序进行重大更改。这包括我们在 Spring 顶级项目中进行的使原生友好的更改、@NativeHint 等基础架构以及我们在 Spring Native 中不断完善的 Spring AOT 构建插件。有关即将发布的步骤的更多信息,请查看我们的路线图。
第二个支柱比 Spring 本身更广泛,原生是一个与 JVM 具有不同特性的平台,但 Java 生态系统需要尽可能保持一致,以避免两种截然不同的 Java 风格,这将难以维护。因此,我们与 GraalVM 团队进行了密切合作,以缩小这一差距。在接下来的几个月中,这项合作将侧重于改进更广泛 JVM 生态系统的原生测试和原生配置。
Spring 开发人员可以通过我们提供的各种示例了解更多关于原生的信息,访问start.spring.io 测试我们新的原生支持,阅读更新的参考指南,阅读发行说明(特别是如果您从早期版本升级),甚至贡献支持您最喜欢的依赖项。如果您想了解更多关于相关的 Spring 商业支持信息,您也可以联系我们。
最后,我要特别感谢已经提供了大量有益反馈和贡献的 Spring 社区,感谢 GraalVM 团队的出色合作,也感谢整个 Spring 团队为使 Spring 开发人员更容易采用原生技术而付出的辛勤努力。
祝您使用愉快!