整体流程
创建过程:
Spring 刷新上下文 -> 实例化 Bean -> 调用初始化 Hook
使用
JpaRepositoryFactoryBean
构建仓库工厂 Bean默认非 Lazy 启动模式下创建仓库实例 -> 创建代理工厂代理该实例 -> 代理工厂使用切面添加多个 Advice:比如方法调用校验器、接口默认方法拦截器、自定义方法实现拦截器、自定义接口实现拦截器
自定义方法实现拦截器
针对自定义方法实现拦截器:QueryExecutorMethodInterceptor
在创建该拦截器时,会使用 Query Lookup Strategy 来查找合适的查询实现,查询实现负责基于该方法使用其参数查询并返回结果,该策略默认值为 CREATE_IF_NOT_FOUND
,会先去找定义的查询:比如先使用基于 @Query
的注解来构建查询,如果不存在则使用 @Procedure
注解构建存储过程查询,最后再尝试查找命名查询,如果都不存在,则使用 PartTreeJpaQuery
构建基于方法名的查询。
PartTreeJpaQuery
将方法名根据前缀模版正则分隔成 主体-Subject
和 谓词-Predicate
两部分,谓词又使用 Or
划分成多个 OrPart
,OrPart
又由 And
拆分为多个 Part
,Part
包含两部分:根据关键字判定为不同的查询条件的类型和该条件对应的实体属性,有了这些 Part
就可以用来构建 javax.criteria.Predicate
并最终构建出 javax.criteria.CriteriaQuery
,这是 JAVAEE/Jakarta 的标准动态查询接口。
该拦截器被作为 Spring AOP 动态代理实现的仓库实例方法的切面通知(Advice)(由于我们是基于接口的代理,内部使用的是 JdkDynamicAopProxy
),当我们调用仓库接口方法时,会通过 AOP 的调用链调用到我们的方法拦截器。