Advanced Native Images Topics
Nested Configuration Properties
春季预先引擎自动为配置属性创建反射提示。然而,不是内部类的嵌套配置属性,*must*使用 `@NestedConfigurationProperty`进行注释,否则它们将不会被检测到,并且不会被绑定。
Reflection hints are automatically created for configuration properties by the Spring ahead-of-time engine.
Nested configuration properties which are not inner classes, however, must be annotated with @NestedConfigurationProperty
, otherwise they won’t be detected and will not be bindable.
其中 `Nested`为:
where Nested
is:
上面的示例为 `my.properties.name`和 `my.properties.nested.number`生成了配置属性。如果没有 `nested`字段上的 `@NestedConfigurationProperty`注释,那么 `my.properties.nested.number`属性在本地镜像中将不可绑定。
The example above produces configuration properties for my.properties.name
and my.properties.nested.number
.
Without the @NestedConfigurationProperty
annotation on the nested
field, the my.properties.nested.number
property would not be bindable in a native image.
在使用构造函数绑定时,您必须使用 `@NestedConfigurationProperty`注释字段:
When using constructor binding, you have to annotate the field with @NestedConfigurationProperty
:
在使用记录时,您必须使用 `@NestedConfigurationProperty`注释参数:
When using records, you have to annotate the parameter with @NestedConfigurationProperty
:
在使用 Kotlin 时,您需要使用 `@NestedConfigurationProperty`注释数据类的参数:
When using Kotlin, you need to annotate the parameter of a data class with @NestedConfigurationProperty
:
请在所有情况下使用公共获取器和设置器,否则这些属性将不可绑定。 |
Please use public getters and setters in all cases, otherwise the properties will not be bindable. |
Converting a Spring Boot Executable Jar
只要 jar 中包含 AOT 生成的资产,就可以将 Spring Boot executable jar 转换为本机映像。这可能在许多情况下很有用,包括:
It is possible to convert a Spring Boot executable jar into a native image as long as the jar contains the AOT generated assets. This can be useful for a number of reasons, including:
-
You can keep your regular JVM pipeline and turn the JVM application into a native image on your CI/CD platform.
-
As
native-image
does not support cross-compilation, you can keep an OS neutral deployment artifact which you convert later to different OS architectures.
可以使用 Cloud Native Buildpacks 或 GraalVM 附带的 native-image
工具将 Spring Boot 可执行 jar 转换为本机映像。
You can convert a Spring Boot executable jar into a native image using Cloud Native Buildpacks, or using the native-image
tool that is shipped with GraalVM.
可执行 jar 必须包括生成的类和 JSON 提示文件等 AOT 生成的资产。 |
Your executable jar must include AOT generated assets such as generated classes and JSON hint files. |
Using Buildpacks
Spring Boot 应用程序通常通过 Maven (mvn spring-boot:build-image
) 或 Gradle (gradle bootBuildImage
) 集成使用 Cloud Native Buildpacks。但是,您还可以使用 pack
将经过 AOT 处理的 Spring Boot 可执行 jar 转换为本机容器映像。
Spring Boot applications usually use Cloud Native Buildpacks through the Maven (mvn spring-boot:build-image
) or Gradle (gradle bootBuildImage
) integrations.
You can, however, also use pack
to turn an AOT processed Spring Boot executable jar into a native container image.
首先,请确保有 Docker 守护程序(有关详细信息,请参见 Get Docker)。如果您使用 Linux,请参见 Configure it to allow non-root user。
First, make sure that a Docker daemon is available (see Get Docker for more details). Configure it to allow non-root user if you are on Linux.
您还需要按照 the installation guide on buildpacks.io 安装 pack
。
You also need to install pack
by following the installation guide on buildpacks.io.
假设正在 target
目录中构建的经过 AOT 处理的 Spring Boot 可执行 jar 是 myproject-0.0.1-SNAPSHOT.jar
,请运行:
Assuming an AOT processed Spring Boot executable jar built as myproject-0.0.1-SNAPSHOT.jar
is in the target
directory, run:
$ 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 即可生成图像。 |
You do not need to have a local GraalVM installation to generate an image in this way. |
一旦 pack
完成,您就可以使用 docker run
启动应用程序:
Once pack
has finished, you can launch the application using 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! 之类的下载管理器下载它。
Another option to turn an AOT processed Spring Boot executable jar into a native executable is to use the GraalVM native-image
tool.
For this to work, you’ll need a GraalVM distribution on your machine.
You can either download it manually on the {url-download-liberica-nik}[Liberica Native Image Kit page] or you can use a download manager like SDKMAN!.
假设正在 target
目录中构建的经过 AOT 处理的 Spring Boot 可执行 jar 是 myproject-0.0.1-SNAPSHOT.jar
,请运行:
Assuming an AOT processed Spring Boot executable jar built as myproject-0.0.1-SNAPSHOT.jar
is in the target
directory, run:
$ 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 对其进行调整。 |
These commands work on Linux or macOS machines, but you will need to adapt them for Windows. |
|
The |
native-image
-cp
标志不接受通配符。您需要确保列出所有 jar(上述命令使用 find
和 tr
完成此操作)。
The native-image
-cp
flag does not accept wildcards.
You need to ensure that all jars are listed (the command above uses find
and tr
to do this).
Using the Tracing Agent
GraalVM 本机映像允许您在 JVM 上拦截反射、资源或代理使用情况,以生成相关提示。Spring 应该自动生成大部分这些提示,但可以快速使用跟踪代理识别缺失的条目。
The GraalVM native image {url-graal-docs-native-image}/metadata/AutomaticMetadataCollection[tracing agent] allows you to intercept reflection, resources or proxy usage on the JVM in order to generate the related hints. Spring should generate most of these hints automatically, but the tracing agent can be used to quickly identify the missing entries.
在使用该代理为本机映像生成提示时,有一些方法:
When using the agent to generate hints for a native image, there are a couple of approaches:
-
Launch the application directly and exercise it.
-
Run application tests to exercise the application.
第一个选项当 Spring 不识别某个库或模式时,对于识别缺少的提示很有用。
The first option is interesting for identifying the missing hints when a library or a pattern is not recognized by Spring.
第二个选项对于可重复设置听起来更有吸引力,但默认情况下,生成的提示将包括测试基础结构所需的任何内容。在应用程序实际运行时,其中一些将是不必要的。为了解决这个问题,该代理支持一个访问筛选器文件,它将导致某些数据从生成输出中排除。
The second option sounds more appealing for a repeatable setup, but by default the generated hints will include anything required by the test infrastructure. Some of these will be unnecessary when the application runs for real. To address this problem the agent supports an access-filter file that will cause certain data to be excluded from the generated output.
Launch the Application Directly
使用以下命令启动带有本机映像跟踪代理的应用程序:
Use the following command to launch the application with the native image tracing agent attached:
$ 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
停止应用程序。
Now you can exercise the code paths you want to have hints for and then stop the application with ctrl-c
.
在应用程序关闭时,本机映像跟踪代理将提示文件写入到给定的配置输出目录。您可以手动检查这些文件,或将它们用作本机映像构建进程的输入。若要将它们用作输入,请将它们复制到 src/main/resources/META-INF/native-image/
目录。下次构建本机映像时,GraalVM 将考虑这些文件。
On application shutdown the native image tracing agent will write the hint files to the given config output directory.
You can either manually inspect these files, or use them as input to the native image build process.
To use them as input, copy them into the src/main/resources/META-INF/native-image/
directory.
The next time you build the native image, GraalVM will take these files into consideration.
可在本机映像跟踪代理上设置更多高级选项,例如按调用类等过滤记录的提示。如需进一步了解,请参阅 {url-graal-docs-native-image}/metadata/AutomaticMetadataCollection[官方文档]。
There are more advanced options which can be set on the native image tracing agent, for example filtering the recorded hints by caller classes, etc. For further reading, please see {url-graal-docs-native-image}/metadata/AutomaticMetadataCollection[the official documentation].
Custom Hints
如果您需要为反射、资源、序列化、代理使用等提供您自己的提示,则可以使用 RuntimeHintsRegistrar
API。创建一个实现 RuntimeHintsRegistrar
接口的类,然后对提供的 RuntimeHints
实例进行适当的调用:
If you need to provide your own hints for reflection, resources, serialization, proxy usage etc. you can use the RuntimeHintsRegistrar
API.
Create a class that implements the RuntimeHintsRegistrar
interface, and then make appropriate calls to the provided RuntimeHints
instance:
然后,您可以在任何 @Configuration
类(例如您带 @SpringBootApplication
注释的应用程序类)上使用 @ImportRuntimeHints
来激活这些提示。
You can then use @ImportRuntimeHints
on any @Configuration
class (for example your @SpringBootApplication
annotated application class) to activate those hints.
如果您有需要绑定的类(主要在序列化或反序列化 JSON 时需要),您可以在任何 bean 上使用 {url-spring-framework-docs}/core/aot.html#aot.hints.register-reflection-for-binding[@RegisterReflectionForBinding
]。大部分提示都是自动推断的,例如在接受或返回 @RestController
方法的数据时。但在直接使用 WebClient
、RestClient
或 RestTemplate
时,您可能需要使用 @RegisterReflectionForBinding
。
If you have classes which need binding (mostly needed when serializing or deserializing JSON), you can use {url-spring-framework-docs}/core/aot.html#aot.hints.register-reflection-for-binding[@RegisterReflectionForBinding
] on any bean.
Most of the hints are automatically inferred, for example when accepting or returning data from a @RestController
method.
But when you work with WebClient
, RestClient
or RestTemplate
directly, you might need to use @RegisterReflectionForBinding
.
Testing custom hints
可以使用 RuntimeHintsPredicates
API 来测试提示。该 API 提供用于构建 Predicate
(可用于测试 RuntimeHints
实例)的方法。
The RuntimeHintsPredicates
API can be used to test your hints.
The API provides methods that build a Predicate
that can be used to test a RuntimeHints
instance.
如果您使用 AssertJ,您的测试将如下所示:
If you’re using AssertJ, your test would look like this:
Known Limitations
GraalVM 本机映像是一项不断发展的技术,并非所有库都提供支持。GraalVM 社区正在提供 reachability metadata 来帮助那些尚未发布自己的项目的项目。Spring 本身并不包含面向第三方库的提示,而是依赖于可达性元数据项目。
GraalVM native images are an evolving technology and not all libraries provide support. The GraalVM community is helping by providing reachability metadata for projects that don’t yet ship their own. Spring itself doesn’t contain hints for 3rd party libraries and instead relies on the reachability metadata project.
如果您在为 Spring Boot 应用程序生成本机映像时遇到问题,请查看 Spring Boot Wiki 的 {url-github-wiki}/Spring-Boot-with-GraalVM[Spring Boot with GraalVM] 页面。您也可以将问题提交到 GitHub 上的 spring-aot-smoke-tests 项目,该项目用于确认常见的应用程序类型按预期工作。
If you encounter problems when generating native images for Spring Boot applications, please check the {url-github-wiki}/Spring-Boot-with-GraalVM[Spring Boot with GraalVM] page of the Spring Boot wiki. You can also contribute issues to the spring-aot-smoke-tests project on GitHub which is used to confirm that common application types are working as expected.
如果您发现某个库不适用于 GraalVM,请在 reachability metadata project 上提出问题。
If you find a library which doesn’t work with GraalVM, please raise an issue on the reachability metadata project.