Spring 数据存储库实际是如何实现的?

How are Spring Data repositories actually implemented?

我在项目中使用 Spring Data JPA 存储库已有一段时间,我知道以下几点:

我对它的编码方式很感兴趣,我查看了 Spring JPA 源代码和 API,但我找不到以下问题的答案:

  1. 如何在 运行 时间生成存储库实现 class 并实现和注入方法?
  2. SpringData JPA 是否使用 CGlib 或任何字节码操作库来实现方法并动态注入?

能否请您帮助解决上述问题并提供任何支持的文档?

首先,没有代码生成,这意味着:没有 CGLib,根本没有字节代码生成。基本方法是使用 Spring 的 ProxyFactory API 以编程方式创建 JDK 代理实例以支持接口,并且 MethodInterceptor 拦截对实例并将方法路由到适当的位置:

  1. 如果存储库已使用自定义实现部分进行初始化(有关详细信息,请参阅 that part of the reference documentation),并且调用的方法是在该 class 中实现的,调用将路由到那里。
  2. 如果方法是查询方法(参见DefaultRepositoryInformation for how that is determined), the store specific query execution mechanism kicks in and executes the query determined to be executed for that method at startup. For that a resolution mechanism is in place that tries to identify explicitly declared queries in various places (using @Query on the method, JPA named queries) eventually falling back to query derivation from the method name. For the query mechanism detection, see JpaQueryLookupStrategy. The parsing logic for the query derivation can be found in PartTree. The store specific translation into an actual query can be seen e.g. in JpaQueryCreator
  3. 如果上面的 none 应用执行的方法必须是由商店特定的存储库基础 class (SimpleJpaRepository 在 JPA 的情况下)实现的方法并且调用是路由到那个实例。

实现该路由逻辑的方法拦截器是QueryExecutorMethodInterceptor,可以找到高级路由逻辑here

这些代理的创建被封装到基于标准 Java 的工厂模式实现中。高级代理创建可以在 RepositoryFactorySupport 中找到。然后,特定于商店的实现添加必要的基础结构组件,以便您可以继续为 JPA 编写如下代码:

EntityManager em = … // obtain an EntityManager
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);

我明确提到这一点的原因是,应该清楚的是,在其核心中,该代码首先不需要 Spring 容器到 运行。它需要 Spring 作为 class 路径上的库(因为我们不想重新发明轮子),但通常与容器无关。

为了简化与 DI 容器的集成,我们当然已经构建了与 Spring Java 配置、XML 命名空间以及 CDI extension 的集成,从而Spring数据可以用于普通CDI场景