Spring Data存储库是如何实际实施的?

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

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

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

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

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


答案 1

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

  1. 如果存储库已使用自定义实现部分进行初始化(有关详细信息,请参阅参考文档的该部分),并且调用的方法在该类中实现,则调用将路由到该类。
  2. 如果该方法是查询方法(有关如何确定该方法,请参阅 DefaultRepositoryInformation),则特定于存储的查询执行机制将启动并执行确定在启动时为该方法执行的查询。为此,已经建立了一种解析机制,该机制尝试在各个位置(在方法上使用JPA命名查询)中显式声明的查询,最终回退到从方法名称派生的查询。有关查询机制检测,请参阅 JpaQueryLookupStrategy。可以在 PartTree 中找到查询派生的分析逻辑。存储对实际查询的特定转换可以在例如JpaQueryCreator中看到。@Query
  3. 如果上述方法都不适用,则执行的方法必须由特定于存储的存储库基类(JPA 情况下为 SimpleJpaRepository)实现,并且调用将路由到该实例中。

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

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

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

我明确提到这一点的原因是,应该清楚的是,在其核心中,该代码的任何内容都不需要Spring容器首先运行。它需要Spring作为类路径上的库(因为我们不想重新发明轮子),但总的来说是容器不可知的。

为了简化与DI容器的集成,我们当然已经构建了与Spring Java配置(XML命名空间)以及CDI扩展的集成,以便Spring Data可以在普通的CDI场景中使用。


答案 2

推荐