Java Spring数据存储库实际上是如何实现的?
我在项目中使用Spring数据JPA存储库已经有一段时间了,我知道以下几点: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
- 在存储库接口中,我们可以添加类似
(假设findbycustomername和phone()
和customerName
是域对象中的字段)phone
- 然后,Spring通过在运行时(在应用程序运行期间)实现上述存储库接口方法来提供实现李>
请您帮助解决上述问题并提供任何支持的文档,好吗?首先,没有代码生成,这意味着:没有CGLib,根本没有字节码生成。基本方法是使用Spring的
ProxyFactory
API以编程方式创建JDK代理实例以支持接口,MethodInterceptor
拦截对实例的所有调用,并将方法路由到适当的位置:
@Query
,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命名查询),最终返回到从方法名称派生的查询。有关查询机制检测,请参阅。查询派生的解析逻辑可以在中找到。具体到实际查询的存储转换可以在中看到,例如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