一篇文章带你深入分析 Spring Data JPA 的原理

我们已经学习了 Spring Data JPA 的基本操作:一篇文章带你快速入门 Spring Data JPA
本篇文章和大家一起分析下,它的运行原理。

一、前期分析

在这里插入图片描述
在上篇文章中,我们发现在自定义的 CustomerDao 中,并没有提供任何方法就可以使用其中的很多方法,那么这些方法究竟是怎么来的呢?

答案很简单,对于我们自定义的Dao接口,由于继承了JpaRepository和JpaSpecificationExecutor,所以我们可以使用这两个接口的所有方法。

所以虽然我们这里定义的是接口,但是真正发挥作用的还是接口的实现类(在程序执行过程中,自动的帮助我们动态的生成了接口的实现类对象)

如何动态的生成实现类对象,就牵扯出来我们前面学过的动态代理(生成基于接口的实现类对象)
动态代理的学习:一篇文章带你搞定什么是动态代理

二、实现过程分析

在使用 Spring Data JPA时,一般实现 JpaRepository 和 JpaSpecificationExecutor 接口,这样就可以使用这些接口中定义的方法,但是这些方法都只是一些声明,没有具体的实现方式,那么在 Spring Data JPA中它又是怎么实现的呢?

(1)JdkDynamicAopProxy
在这里插入图片描述
断点执行到方法上时,我们可以发现注入的 customerDao 对象,本质上是通过 JdkDynamicAopProxy 生成的一个代理对象
(2)进入 JdkDynamicAopProxy
在这里插入图片描述
看到了我们熟悉的 InvocationHandler,所以里面必定会有一个 invoke 执行具体的代理方法从而帮助我们去创建接口的实现类:
在这里插入图片描述
这里的 target 就是生成的动态代理对象。

当程序执行的时候,会通过JdkDynamicAopProxy的invoke方法,对customerDao对象生成动态代理对象。根据对Spring Data JPA介绍而知,要想进行findOne查询方法,最终还是会出现JPA规范的API完成操作,那么这些底层代码存在于何处呢?

答案很简单,都隐藏在通过JdkDynamicAopProxy生成的动态代理对象当中,而这个动态代理对象就是SimpleJpaRepository

(3)进入 SimpleJpaRepository
在这里插入图片描述
很熟悉的两个接口,JpaRepository 和 JpaSpecificationExecutor 在这里被继承,就说明这个方法一定也实现这两个接口的所有方法,所以实际上 SimpleJpaRepository 也可以理解为这两个接口的实现类,也可以认为就是客户 dao 的实现类,因为它实现了这两个接口的所有方法。

所以该类中必然会有我们要查找 findOne 的实现:
在这里插入图片描述
通过打断点测试,发现确实进入走了该类中的findOne方法,可以看到最后返回的是 em.find 操作

(4)进一步查看 em 具体指什么:
在这里插入图片描述
带着问题继续查找em对象,我们发现em就是EntityManager对象,而他是JPA原生的实现方式,所以我们得到结论Spring Data JPA只是对标准JPA操作进行了进一步封装,简化了Dao层代码的开发,
它执行的 findOne 方法实际上还是 JPA 操作里的 find 方法操作的封装。

三、调用过程分析

(1)通过JdkDynamicAopProxy的invoke方法创建了一个动态代理对象
(2)SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD)
(3)通过hibernate完成数据库操作(封装了jdbc)

在这里插入图片描述
具体实现过程分析:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/nanhuaibeian/article/details/107291089