Solon v4.0.5

native 自动化处理清单

</> markdown
2026年8月12日 上午11:20:57

Solon AOT 在编译时会自动启动一次应用(用于收集容器信息),然后把能探测到的东西全部登记成 GraalVM 原生元数据。本文回答两个问题:

  1. 框架自动替你做了什么?(开箱即用清单)
  2. 框架不自动处理什么?(需要手动登记的部分)

1、AOT 阶段自动完成的四件事

执行 -P aot(或 -P native)打包时,solon-maven-plugin:process-aot 会触发 SolonAotProcessor

步骤说明
1. 真实启动应用调用主类的 main 方法启动 Solon(NativeDetector.isAotRuntime() 为 true),通过自然运行收集容器信息
2. 生成代理类 Java 源码为被代理的 bean 生成 Xxx$$SolonAotProxy.java(javapoet 生成源码,由 Maven 编译,运行时不再需要 ASM)
3. 生成原生元数据写出 reflect-config.json 、 resource-config.json 、 serialization-config.json 、 proxy-config.json 、 native-image.properties
4. 生成 Solon 私有资源索引把扫描到的资源清单写入 solon-resource.json,供 native 运行时做资源扫描

产物统一输出到:target/classes/META-INF/native-image/<应用包路径>/

2、自动注册的"类"(→ reflect-config.json)

自动注册内容注册粒度备注
所有非接口 bean 类默认构造(若有)+ DECLARED_FIELDS + INVOKE_DECLARED_CONSTRUCTORS接口类型的 bean 不自动处理
bean 的全部字段(含父类字段)逐字段登记 + DECLARED_FIELDS字段声明类也会登记
bean 的 init / destroy 方法INVOKE对应 @Init / @PreDestroy
所有 handler 方法(methodForeach)方法 + 参数类型 + 参数泛型 + 返回类型 + 返回泛型见下方"序列化边界"
被代理 bean 的方法(methodEgggs)同上代理 bean 的方法会全部登记
@Inject("${..}") 注入的配置实体类INVOKE_DECLARED_CONSTRUCTORS + INVOKE_PUBLIC_METHODS@Inject("${user}") UserConfig
JDK 代理注入的接口写入 proxy-config.json如注入值是 Proxy 实例的接口
JDBC Driver(DriverManager 枚举到的)INVOKE_DECLARED_CONSTRUCTORS驱动类会全部登记
InvocationHandlerINVOKE_DECLARED_METHODSJDK 动态代理需要
插件类(plugins 配置中带类名)默认构造手动 registerPlugin 的除外
6 个 extend impl 类(存在才注册)默认构造PropsLoaderExt / PropsConverterExt / AppClassLoaderExt / RuntimeServiceExt / ProxyBinderExt / ActionLoaderFactoryExt
被代理 bean 的 $$SolonAotProxy 静态代理类构造器 (InvocationHandler) + INVOKE_DECLARED_CONSTRUCTORS代理类构造时需要反射

注意:bean 的成员方法本身(普通业务方法)不会自动登记,登记的是 handler 方法(映射方法)与代理 bean 的方法。如果你的代码在运行时对普通 bean 的方法做反射调用,需要手动登记。

3、自动注册的"资源"(→ resource-config.json)

固定登记 6 个前缀模式:

资源模式说明
app.*\.yml应用配置
app.*\.properties应用配置
META-INF/.*包内元信息(插件、SPI 等)
WEB-INF/.*Web 资源
static/.*静态资源
templates/.*模板资源

同时,AOT 会按 include 清单扫描 classpath,把命中的资源文件路径写入 solon-resource.json(排除 META-INF/maven/)。native 运行时 ScanUtil / ResourceUtil 就是从这份清单里找资源的。

4、序列化自动注册的边界(重点)

场景是否自动注册说明
方法参数类型(非 java.* 且实现 Serializable)自动通过 handler 方法 / 代理 bean 方法登记时顺带注册
方法返回值类型(同上)自动同上
方法参数/返回值的泛型实参自动(反射登记)泛型信息也会登记
普通 bean 类(即使实现了 Serializable)不自动需要手动 registerSerialization
lambda 序列化不自动需要手动 registerLambdaSerialization

也就是说:只有"方法参数/返回值"路径上的 Serializable 类才会被自动登记序列化;其它需要 Java 序列化的类,需要手动补 metadata.registerSerialization(...)

5、不自动处理、需要手动登记的内容

内容处理方式
第三方框架的反射(类、方法、字段、构造器)RuntimeNativeRegistrar 手动登记(B/C 类第三方)
第三方框架的资源文件registerResourceInclude 手动登记
自定义资源路径(如 acme.zip、nginx.conf、banner.txt)registerResourceInclude 手动登记
一般 bean / 自定义类的 Java 序列化registerSerialization 手动登记
lambda 序列化registerLambdaSerialization 手动登记
动态编译 / 字节码生成(如 CGLIB、ASM 动态代理)无法支持,换方案
运行时才动态加载的类无法探测,需手动登记

6、如何验证 AOT 是否生效

打包完成后,检查 target/classes/META-INF/native-image/<应用包路径>/ 目录:

native-image.properties     # 默认参数(-H:Class、--no-fallback 等)
reflect-config.json         # 反射登记(应该有你的 bean)
resource-config.json        # 资源登记
serialization-config.json   # 序列化登记(可能为空)
proxy-config.json           # JDK 代理接口(可能为空)
solon-resource.json         # Solon 私有资源索引

再检查 target/generated-sources/ 下是否生成了 Xxx$$SolonAotProxy.java 代理源码。两者都在,说明 AOT 处理已生效。

7、默认的 native-image 参数

native-image.properties 默认写入(可通过 metadata.registerArg(...) 追加):

-H:Class=<应用主类>
--report-unsupported-elements-at-runtime
--no-fallback
--install-exit-handlers

-P native 还会额外启用 GraalVM 官方可达性元数据仓库(add-reachability-metadata),许多自带元数据的第三方库(如 mysql-connector-java 8.x)因此可以直接构建。