Advanced Native Images Topics

Nested Configuration Properties

春季预先引擎自动为配置属性创建反射提示。然而,不是内部类的嵌套配置属性,*must*使用 `@NestedConfigurationProperty`进行注释,否则它们将不会被检测到,并且不会被绑定。

其中 `Nested`为:

上面的示例为 `my.properties.name`和 `my.properties.nested.number`生成了配置属性。如果没有 `nested`字段上的 `@NestedConfigurationProperty`注释,那么 `my.properties.nested.number`属性在本地镜像中将不可绑定。

在使用构造函数绑定时,您必须使用 `@NestedConfigurationProperty`注释字段:

在使用记录时,您必须使用 `@NestedConfigurationProperty`注释参数:

在使用 Kotlin 时,您需要使用 `@NestedConfigurationProperty`注释数据类的参数:

请在所有情况下使用公共获取器和设置器,否则这些属性将不可绑定。

Converting a Spring Boot Executable Jar

只要 jar 中包含 AOT 生成的资产,就可以将 Spring Boot executable jar 转换为本机映像。这可能在许多情况下很有用,包括:

  • 您可以保留常规 JVM 进程并将 JVM 应用程序转换为 CI/CD 平台上的本机映像。

  • native-image does not support cross-compilation 所述,您可以保留一个操作系统中立的部署工件,之后将其转换为不同的操作系统架构。

可以使用 Cloud Native Buildpacks 或 GraalVM 附带的 native-image 工具将 Spring Boot 可执行 jar 转换为本机映像。

可执行 jar 必须包括生成的类和 JSON 提示文件等 AOT 生成的资产。

Using Buildpacks

Spring Boot 应用程序通常通过 Maven (mvn spring-boot:build-image) 或 Gradle (gradle bootBuildImage) 集成使用 Cloud Native Buildpacks。但是,您还可以使用 pack 将经过 AOT 处理的 Spring Boot 可执行 jar 转换为本机容器映像。

首先,请确保有 Docker 守护程序(有关详细信息,请参见 Get Docker)。如果您使用 Linux,请参见 Configure it to allow non-root user

您还需要按照 the installation guide on buildpacks.io 安装 pack

假设正在 target 目录中构建的经过 AOT 处理的 Spring Boot 可执行 jar 是 myproject-0.0.1-SNAPSHOT.jar,请运行:

$ pack build --builder paketobuildpacks/builder-jammy-tiny \
    --path target/myproject-0.0.1-SNAPSHOT.jar \
    --env 'BP_NATIVE_IMAGE=true' \
    my-application:0.0.1-SNAPSHOT

您无需本地安装 GraalVM 即可生成图像。

一旦 pack 完成,您就可以使用 docker run 启动应用程序:

$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT

Using GraalVM native-image

将经过 AOT 处理的 Spring Boot 可执行 jar 转换为本机可执行文件的另一种选择是使用 GraalVM native-image 工具。要使其正常工作,您的机器上需要有 GraalVM 发行版。您可以手动在 {url-download-liberica-nik}[Liberica Native Image Kit 页面] 上下载它,也可以使用如 SDKMAN! 之类的下载管理器下载它。

假设正在 target 目录中构建的经过 AOT 处理的 Spring Boot 可执行 jar 是 myproject-0.0.1-SNAPSHOT.jar,请运行:

$ rm -rf target/native
$ mkdir -p target/native
$ cd target/native
$ jar -xvf ../myproject-0.0.1-SNAPSHOT.jar
$ native-image -H:Name=myproject @META-INF/native-image/argfile -cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'`
$ mv myproject ../

这些命令适用于 Linux 或 macOS 机器,但是您需要根据 Windows 对其进行调整。

@META-INF/native-image/argfile 可能不会打包在您的 jar 中。它仅在需要覆盖可访问性元数据时才会包含在内。

native-image -cp 标志不接受通配符。您需要确保列出所有 jar(上述命令使用 findtr 完成此操作)。

Using the Tracing Agent

GraalVM 本机映像允许您在 JVM 上拦截反射、资源或代理使用情况,以生成相关提示。Spring 应该自动生成大部分这些提示,但可以快速使用跟踪代理识别缺失的条目。

在使用该代理为本机映像生成提示时,有一些方法:

  • 直接启动应用程序并使用它。

  • 运行应用程序测试来使用应用程序。

第一个选项当 Spring 不识别某个库或模式时,对于识别缺少的提示很有用。

第二个选项对于可重复设置听起来更有吸引力,但默认情况下,生成的提示将包括测试基础结构所需的任何内容。在应用程序实际运行时,其中一些将是不必要的。为了解决这个问题,该代理支持一个访问筛选器文件,它将导致某些数据从生成输出中排除。

Launch the Application Directly

使用以下命令启动带有本机映像跟踪代理的应用程序:

$ java -Dspring.aot.enabled=true \
    -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ \
    -jar target/myproject-0.0.1-SNAPSHOT.jar

现在,您可以运行您希望具有提示的代码路径,然后使用 ctrl-c 停止应用程序。

在应用程序关闭时,本机映像跟踪代理将提示文件写入到给定的配置输出目录。您可以手动检查这些文件,或将它们用作本机映像构建进程的输入。若要将它们用作输入,请将它们复制到 src/main/resources/META-INF/native-image/ 目录。下次构建本机映像时,GraalVM 将考虑这些文件。

可在本机映像跟踪代理上设置更多高级选项,例如按调用类等过滤记录的提示。如需进一步了解,请参阅 {url-graal-docs-native-image}/metadata/AutomaticMetadataCollection[官方文档]。

Custom Hints

如果您需要为反射、资源、序列化、代理使用等提供您自己的提示,则可以使用 RuntimeHintsRegistrar API。创建一个实现 RuntimeHintsRegistrar 接口的类,然后对提供的 RuntimeHints 实例进行适当的调用:

然后,您可以在任何 @Configuration 类(例如您带 @SpringBootApplication 注释的应用程序类)上使用 @ImportRuntimeHints 来激活这些提示。

如果您有需要绑定的类(主要在序列化或反序列化 JSON 时需要),您可以在任何 bean 上使用 {url-spring-framework-docs}/core/aot.html#aot.hints.register-reflection-for-binding[@RegisterReflectionForBinding]。大部分提示都是自动推断的,例如在接受或返回 @RestController 方法的数据时。但在直接使用 WebClientRestClientRestTemplate 时,您可能需要使用 @RegisterReflectionForBinding

Testing custom hints

可以使用 RuntimeHintsPredicates API 来测试提示。该 API 提供用于构建 Predicate (可用于测试 RuntimeHints 实例)的方法。

如果您使用 AssertJ,您的测试将如下所示:

Known Limitations

GraalVM 本机映像是一项不断发展的技术,并非所有库都提供支持。GraalVM 社区正在提供 reachability metadata 来帮助那些尚未发布自己的项目的项目。Spring 本身并不包含面向第三方库的提示,而是依赖于可达性元数据项目。

如果您在为 Spring Boot 应用程序生成本机映像时遇到问题,请查看 Spring Boot Wiki 的 {url-github-wiki}/Spring-Boot-with-GraalVM[Spring Boot with GraalVM] 页面。您也可以将问题提交到 GitHub 上的 spring-aot-smoke-tests 项目,该项目用于确认常见的应用程序类型按预期工作。

如果您发现某个库不适用于 GraalVM,请在 reachability metadata project 上提出问题。