Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring数据存储库实际上是如何实现的?_Java_Spring_Spring Data_Repository Pattern_Ddd Repositories - Fatal编程技术网

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

Java Spring数据存储库实际上是如何实现的?,java,spring,spring-data,repository-pattern,ddd-repositories,Java,Spring,Spring Data,Repository Pattern,Ddd Repositories,我在项目中使用Spring数据JPA存储库已经有一段时间了,我知道以下几点: 在存储库接口中,我们可以添加类似findbycustomername和phone()(假设customerName和phone是域对象中的字段) 然后,Spring通过在运行时(在应用程序运行期间)实现上述存储库接口方法来提供实现 我对这段代码是如何编写的很感兴趣,并且我已经查看了Spring JPA源代码和API,但是我找不到以下问题的答案: 如何在运行时生成存储库实现类&如何实现和注入方法 SpringData

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

  • 在存储库接口中,我们可以添加类似
    findbycustomername和phone()
    (假设
    customerName
    phone
    是域对象中的字段)
  • 然后,Spring通过在运行时(在应用程序运行期间)实现上述存储库接口方法来提供实现
我对这段代码是如何编写的很感兴趣,并且我已经查看了Spring JPA源代码和API,但是我找不到以下问题的答案:

  • 如何在运行时生成存储库实现类&如何实现和注入方法
  • SpringDataJPA是否使用CGlib或任何字节码操作库来实现方法和动态注入

  • 请您帮助解决上述问题并提供任何支持的文档,好吗?

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

  • 如果存储库已使用自定义实现部分初始化(有关详细信息,请参阅),并且调用的方法在该类中实现,则调用将路由到该类
  • 如果该方法是一个查询方法(请参阅以了解如何确定),则特定于存储的查询执行机制将启动并执行确定在启动时为该方法执行的查询。为此,有一种解析机制,它尝试在不同的位置识别显式声明的查询(使用方法上的
    @Query
    ,JPA命名查询),最终返回到从方法名称派生的查询。有关查询机制检测,请参阅。查询派生的解析逻辑可以在中找到。具体到实际查询的存储转换可以在中看到,例如
  • 如果上述方法都不适用,则执行的方法必须是由特定于存储库的基类(对于JPA)实现的方法,并且调用被路由到该基类的实例中
  • 实现路由逻辑的方法拦截器是
    QueryExecutorMethodInterceptor
    ,可以找到高级路由逻辑

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

    EntityManager em = … // obtain an EntityManager
    JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
    UserRepository repository = factory.getRepository(UserRepository.class);
    
    我明确提到这一点的原因是,应该很清楚,在其核心中,这些代码中没有任何一个首先需要运行Spring容器。它需要Spring作为类路径上的一个库(因为我们不想重新发明轮子),但总体上是容器无关的


    为了简化与DI容器的集成,我们当然构建了与SpringJava配置的集成,这是一个XML名称空间,也是一个XML名称空间,这样Spring数据可以在普通CDI场景中使用。

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

  • 如果存储库已使用自定义实现部分初始化(有关详细信息,请参阅),并且调用的方法在该类中实现,则调用将路由到该类
  • 如果该方法是一个查询方法(请参阅以了解如何确定),则特定于存储的查询执行机制将启动并执行确定在启动时为该方法执行的查询。为此,有一种解析机制,它尝试在不同的位置识别显式声明的查询(使用方法上的
    @Query
    ,JPA命名查询),最终返回到从方法名称派生的查询。有关查询机制检测,请参阅。查询派生的解析逻辑可以在中找到。具体到实际查询的存储转换可以在中看到,例如
  • 如果上述方法都不适用,则执行的方法必须是由特定于存储库的基类(对于JPA)实现的方法,并且调用被路由到该基类的实例中
  • 实现路由逻辑的方法拦截器是
    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名称空间,也是一个XML名称空间,这样Spring数据就可以在普通CDI场景中使用。

    Hi Oliver,您能否详细说明Spring首先是如何发现
    @Repository
    带注释的接口的?查看
    RepositoryFactorySupport#getRepository()
    可以看出它将接口类作为参数,因此它必须是disco