java - Spring Data 存储库实际上是如何实现的?

标签 java spring spring-data repository-pattern ddd-repositories

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

  • 在存储库接口(interface)中,我们可以添加诸如 findByCustomerNameAndPhone() 之类的方法(假设 customerNamephone 是域对象中的字段)。
  • 然后,Spring 通过在运行时(应用程序运行期间)实现上述存储库接口(interface)方法来提供实现。

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

  1. 运行时生成的存储库实现类以及方法是如何实现和注入(inject)的?
  2. Spring Data JPA 是否使用 CGlib 或任何字节码操作库来实现方法并动态注入(inject)?

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

最佳答案

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

  1. 如果已使用自定义实现部分初始化存储库(有关详细信息,请参阅 that part of the reference documentation),并且调用的方法在该类中实现,则调用将路由到那里。
  2. 如果该方法是查询方法(请参阅 DefaultRepositoryInformation 了解如何确定),则存储特定查询执行机制将启动并执行确定在启动时为该方法执行的查询。为此,存在一种解析机制,尝试识别在不同位置显式声明的查询(在方法上使用 @Query ,JPA 命名查询),最终回退到从方法名称派生查询。查询机制检测参见JpaQueryLookupStrategy 。查询派生的解析逻辑可以在PartTree中找到。 。可以看到商店特定的翻译为实际查询:在 JpaQueryCreator .
  3. 如果以上都不适用,则执行的方法必须是由特定于商店的存储库基类(在 JPA 的情况下 SimpleJpaRepository)实现的方法,并且调用将路由到该实例的实例中。

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

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

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

我明确提到这一点的原因是,应该清楚的是,从本质上讲,该代码的任何内容都不需要 Spring 容器来运行。它需要 Spring 作为类路径上的库(因为我们不喜欢重新发明轮子),但通常与容器无关。

为了简化与 DI 容器的集成,我们当然还构建了与 Spring Java 配置、XML 命名空间以及 CDI extension 的集成。 ,这样Spring Data就可以在普通的CDI场景中使用了。

关于java - Spring Data 存储库实际上是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40579272/

相关文章:

java - System.getProperty 为定义的属性返回 null

java - Scala 方式进行 apache commons lang3 验证?

java - 将任务从 EDT 分派(dispatch)到 main?

java - 在 Java 中,使用 Poll 方法的 Azure 动态刷新不适用于 Spring Boot 3.x.x

java - 实体 JPA/Hibernate 中的条件 JoinColumn

java - 无法在 android webview 中加载屏幕?

java - Spring 自定义基于条件的验证

java - 使用子字段版本使用 Spring Data 进行乐观锁定

spring-data - 如何在spring数据couchbase中设置couchbase操作超时?

java - 如何使用 Mongo Repository 查询同一个字段两次?