我在项目中使用spring data jpa存储库已经有一段时间了,我知道以下几点:
在存储库接口中,我们可以添加如下方法 findByCustomerNameAndPhone()
(假设 customerName
以及 phone
域对象中的字段)。
然后,spring通过在运行时(在应用程序运行期间)实现上述存储库接口方法来提供实现。
我对这段代码是如何编写的很感兴趣,我也查看了spring jpa源代码和API,但我找不到以下问题的答案:
如何在运行时生成存储库实现类&实现和注入方法?
springdatajpa是否使用cglib或任何字节码操作库来实现方法和动态注入?
您能帮我解答上述问题并提供任何支持的文档吗?
1条答案
按热度按时间osh3o9ms1#
首先,没有代码生成,这意味着:没有cglib,没有字节码生成。基本方法是使用spring的
ProxyFactory
api来支持接口和MethodInterceptor
拦截对示例的所有调用,并将方法路由到适当的位置:如果已使用自定义实现部分初始化存储库(有关详细信息,请参阅参考文档的该部分),并且调用的方法是在该类中实现的,则调用将路由到该类中。
如果方法是查询方法(请参阅
DefaultRepositoryInformation
对于如何确定,存储特定的查询执行机制启动并执行在启动时为该方法确定要执行的查询。为此,有一个解析机制,它尝试在不同的位置识别显式声明的查询(使用@Query
在方法上,jpa(命名查询)最终从方法名返回到查询派生。有关查询机制检测,请参阅JpaQueryLookupStrategy
. 查询派生的解析逻辑可以在中找到PartTree
. 具体到实际查询的存储转换可以在JpaQueryCreator
.如果以上都不适用,则执行的方法必须是由特定于存储库的基类实现的方法(
SimpleJpaRepository
在jpa的情况下),调用被路由到该示例中。实现路由逻辑的方法拦截器是
QueryExecutorMethodInterceptor
,可以在这里找到高级路由逻辑。这些代理的创建被封装到标准的基于java的工厂模式实现中。高级代理创建可以在中找到
RepositoryFactorySupport
. 然后,特定于商店的实现会添加必要的基础结构组件,以便对于jpa,您可以继续编写如下代码:我明确提到这一点的原因是,应该很清楚,在其核心中,这些代码中没有任何一个首先需要运行spring容器。它需要spring作为类路径上的一个库(因为我们不希望重新发明轮子),但一般来说它不受容器的影响。
为了简化与di容器的集成,我们当然构建了与springjava配置的集成,一个xml名称空间,还有一个cdi扩展,这样spring数据可以在普通cdi场景中使用。