我的架构梦:(十二)Spring Data JPA 源码分析

Spring Data JPA 源码分析

    • 一、前言
    • 二、这个代理对象是怎么产生,过程是怎样的?
    • 三、这个代理对象类型SimpleJpaRepository有什么特别的?

一、前言

Spring Data JPA 源码很少有人去分析,原因如下:

1、Spring Data JPA 地位没有之前学习的框架高,大家习惯把它当成一个工具来用了,不愿意对它进行源码层次的解读。

2、开发Dao接口(ResumeDao),接口的实现对象肯定是通过动态代理来完成的(增强),代理对象的产生过程追源码很难追,特别特别讲究技巧。

这里,我来和大家一起分析下源码,Spring Data JPA源码剖析的主要的过程,就是代理对象产生的过程。

我们发现resumeDao是一个代理对象,这个代理对象的类型是SimpleJapRepository。代理对象在h里产生。

我的架构梦:(十二)Spring Data JPA 源码分析_第1张图片

二、这个代理对象是怎么产生,过程是怎样的?

以往:如果要给一个对象产生代理对象,我们知道是在AbstractApplicationContextrefresh方法中, 那么能不能在这个方法中找到什么我们当前场景的线索?

我的架构梦:(十二)Spring Data JPA 源码分析_第2张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第3张图片

进入该方法以后,断点到这一行,输入beanName.equals("resumeDao")

我的架构梦:(十二)Spring Data JPA 源码分析_第4张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第5张图片

新的疑问又来了?

问题1: 为什么会给它指定为一个JpaRespositoryFactoryBean#getObject方法返回具体的对象?

问题2:指定这个FactoryBean是在什么时候发生的?

首先解决问题2:

我的架构梦:(十二)Spring Data JPA 源码分析_第6张图片

传入一个resumeDao就返回了一个已经指定classJpaRepositoryFactoryBeanBeanDefinition对象了,那么应该在上图中的get时候就有了,所以断点进入:

private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap(256);

在这里插入图片描述

问题来了,什么时候putmap中去的?我们定位到了一个方法在做这件事:

mergedBeanDefinitions.put Find Usages 反调找到该方法:

我的架构梦:(十二)Spring Data JPA 源码分析_第7张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第8张图片
我们发现,传入该方法的时候,BeanDefintion中的class就已经被指定为FactoryBean了,那么观察该方法的调用栈。

我的架构梦:(十二)Spring Data JPA 源码分析_第9张图片
我的架构梦:(十二)Spring Data JPA 源码分析_第10张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第11张图片
我的架构梦:(十二)Spring Data JPA 源码分析_第12张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第13张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第14张图片
继续跟进,发现 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configuration.getRepositoryFactoryBeanClassName());这行代码已经产生了JpaRepositoryFactoryBean
我的架构梦:(十二)Spring Data JPA 源码分析_第15张图片

在这里插入图片描述

在这里插入图片描述

通过上述追踪我们发现,,扫描到的接口,在进行BeanDefintion 注册时候,class会被固定的指定为JpaRepositoryFacotryBean

至此,问题2 追踪完毕。


那么接下来,我们再来追踪问题1 JpaRespositoryFactoryBean是一个什么样的类,它是一个FactoryBean,我们重点关注FactoryBeangetObject方法。

我的架构梦:(十二)Spring Data JPA 源码分析_第16张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第17张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第18张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第19张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第20张图片

在这里插入图片描述

我的架构梦:(十二)Spring Data JPA 源码分析_第21张图片

我的架构梦:(十二)Spring Data JPA 源码分析_第22张图片
我的架构梦:(十二)Spring Data JPA 源码分析_第23张图片

由此可⻅,JdkDynamicAopProxy会生成一个代理对象类型为SimpleJpaRespository,而该对象的增强逻辑就在JdkDynamicAopProxy类的invoke方法中。

至此,问题1追踪完毕。

三、这个代理对象类型SimpleJpaRepository有什么特别的?

我的架构梦:(十二)Spring Data JPA 源码分析_第24张图片

在这里插入图片描述

原来SimpleJpaRepository类实现了JpaRepository接口和JpaSpecificationExecutor接口。

我的架构梦:(十二)Spring Data JPA 源码分析_第25张图片

Spring Data JPA 级别的封装也就到这了,剩下的是JPAhibernate的源码了,这也印证了我们刚开始讲的Spring Data JPA是对JPA的高级封装。

你可能感兴趣的:(我的架构梦)