提前优化
本章介绍了Spring Data的提前时间优化(AOT),这些优化建立在Spring的提前时间优化之上。
提前代码生成
提前代码生成不仅限于使用 GraalVM 原生映像,还在常规部署中具有优势,并有助于优化 jvm 的启动性能。
|
在AOT优化中,一些决策(比如数据库方言)会在构建时被冻结,并直接包含在应用设置中。 |
如果启用了预编译,Spring Data(取决于实际使用的模块)可以在AOT阶段贡献多个组件。
-
用于生成类型/属性访问器的字节码
-
定义仓库接口的源代码
-
JSON 格式的存储元数据
上述所有功能默认都是开启的。 不过,用户可以通过以下选项进行微调配置。
|
布尔标志用于控制生成类型/属性访问器中字节码的贡献 |
|
逗号分离的FQCN列表,用于生成的类型/属性访问器贡献字节码。
蚁式包括与包裹名称匹配的图案(例如: |
|
FQCN 的逗号分离列表,用于跳过生成的类型/属性访问器中字节码的贡献。
Ant式排除与包名称匹配的模式(例如: |
|
用于控制仓库接口源代码贡献的布尔标志 |
|
布尔标志用于控制某个模块仓库接口源代码的贡献(例如, |
|
布尔标志用于控制包含查询方法和实际查询字符串的 JSON 存储库元数据的贡献。
需要 |
提前存储库
|
预先存储库仅适用于特定模块的命令式(非响应式)存储库接口。 识别合格查询方法的标准因实现模块而异。 |
AOT 仓库是 AOT 处理的扩展,通过预生成合格的查询方法实现实现。 查询方法对开发者来说是不透明的,其底层查询是否在查询方法调用中被执行。 AOT 仓库贡献基于导出、注释和命名查询的查询方法实现,这些查询在构建时已知。 这种优化将查询方法的处理从运行时转移到构建时,这可以显著提升性能,因为查询方法无需在每次应用启动时进行反思分析。
最终生成的AOT仓库片段遵循以下命名方案:<仓库FQCN>Impl__AotRepository并且被放置在与仓库接口相同的包中。
|
可以把AOT仓库类看作内部优化。 不要直接在代码中使用它们,因为生成和实现细节可能会在未来版本中发生变化。 |
存储库元数据
AOT 处理内省查询方法并收集关于仓库查询的元数据。 Spring Data 将这些元数据存储在同一包内以源仓库命名的 JSON 文件中。 仓库 JSON 元数据包含查询和片段的详细信息。 以下仓库示例如下:
-
Metadata
-
Repository
{
"name": "example.springdata.UserRepository",
"module": "JDBC",
"type": "IMPERATIVE",
"methods": [
{
"name": "findBy",
"signature": "public abstract java.util.List<example.springdata.User> example.springdata.UserRepository.findBy()",
"query": {
"query": "SELECT * FROM User"
}
},
{
"name": "findByLastnameStartingWith",
"signature": "public abstract org.springframework.data.domain.Page<example.springdata.User> example.springdata.UserRepository.findByLastnameStartingWith(java.lang.String,org.springframework.data.domain.Pageable)",
"query": {
"query": "SELECT * FROM User u WHERE lastname LIKE :lastname",
"count-query": "SELECT COUNT(*) FROM User WHERE lastname LIKE :lastname"
}
},
{
"name": "findByEmailAddress",
"signature": "public abstract example.springdata.User example.springdata.UserRepository.findByEmailAddress(java.lang.String)",
"query": {
"query": "select * from User where emailAddress = ?1"
}
},
interface UserRepository extends CrudRepository<User, Integer> {
List<User> findBy();
Page<User> findByLastnameStartingWith(String lastname, Pageable page);
@Query("select * from User where emailAddress = ?1")
User findByEmailAddress(String username);
}
|
创建JSON元数据可以通过以下方式进行控制。 |
原生图像运行提示
作为原生镜像运行应用需要比普通JVM运行时更多的信息。 Spring Data 在 AOT 处理过程中为本地图像使用提供运行时提示。 这些特别的提示是:
-
审计
-
管理类型以捕捉类路径扫描的结果 -
存储 库
-
实体、返回类型和 Spring Data 注释的反射提示
-
存储库片段
-
Querydsl
Q类 -
Kotlin 协程支持
-
-
网页支持(Jackson 提示
PagedModel)
JPA提前存储库
AOT仓库包括符合AOT处理资格的过滤方法。 这些通常是没有实现片段支持的查询方法。
|
AOT处理避免了数据库访问。
因此,它初始化内存中的休眠实例以收集元数据。
休眠配置的类型由我们的AOT元数据收集器决定。
我们更倾向于 |
支持的功能
-
派生查询方法,
@Query/@NativeQuery以及命名查询方法 -
注释为
@Procedure -
@Modifying方法返回无效或智力 -
@QueryHints支持 -
分页
片,流和自选返回类型 -
排序查询重写
-
接口与DTO投影
-
价值表达(这些需要一些反思性信息。 请注意,使用值表达式需要表达式解析和上下文信息来评估表达式)
局限性
-
处理进攻的目标需要休眠。
-
QueryRewriter一定是没有 args 的课程。QueryRewriter豆子尚未被支持。 -
接受方法
卷轴位置(例如:密钥集页码)尚未得到支持。 -
自定义集合返回类型(例如
io.vavr.collection,“org.eclipse.collections)尚未得到支持。
排除方法
-
原油仓库、Querydsl、Query by Example以及其他基接口方法,因为它们的实现由基类各自的片段提供 -
实现过于复杂的方法
-
接受方法
卷轴位置(例如:密钥集页码) -
动态投影
-