写了个SpringDataJPA的Demo并Debugger追踪了一下它的源码执行过程,以根据ID查询为例
如下:
我们在使用SpringDataJPA时只用定义接口并继承JpaRepository,JpaSpecificationExecutor这么两个接口,然后就可以实现简单的增删改查功能,看似啥都不用写,其实在调用时源码会通过动态代理帮我们实现这些方法。
/**
* @author LiuK
* @date 2019/1/22 9:28
* @description:
*/
public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Long> {
}
- 我们调用的是接口中并没有实现的方法方法,在调用时会使用动态代理模式动态生成实现方法。
在Debugger窗口里会发现JdkDynamicAopProxy
- 去查看JdkDynamicAopProxy@4755的原码,实现了InvocationHandler中的invoke增强方法,当执行invoke方法时就会帮我们Dao对象接口生成实现类
- 在invoke实现接口的方法里:Object target就是动态代理对象 我们可以观察到SimpleJpaRepository这个动态代理对象
- 现在去看SimpleJpaRepository的源码;操作:在debugger窗口找到target里的SimpleJpaRepository右键选择Jump To Type Source进入源码
- SimpleJpaRepository源码–>可以发现他与我们自己写的dao接口所继承的接口一致
自己写的接口:
SimpleJpaRepository源码:
- 看SimpleJpaRepository的类结构图可以发现基本增删改查方法都被实现了
- 验证前面定义的findOne()方法:我们可以观察到确实SimpleJpaRepository里的findOne执行了
测试方法:
SimpleJpaRepostory里的findOne:
- SimpleJpaRepostory的findOne方法最后一句的em代表实体管理器EntityManager对象,点进去看一下:em会执行他的find方法
总结:
1.通过JdkDynamicAopProxy的invoke方法创建了一个动态代理对象
2.SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD)
3.通过hibernate完成数据库操作(封装了jdbc)
就到这里了 ,整过过程就是一个动态代理的实现过程,也就是动态代理帮助我们不用写那些基础的代码。表述的不清楚,主要是展示debugger的过程,相信跟着debugger一遍就会明白的。