SpringDataJpa源码理解

上一篇讲解了SpringDataJpa的基本使用,下面简单说一下源码
我们以其中的一个test为案例进行分析:

我们可以发现resumeDao它是一个代理对象,类型是SimpleJpaRepository,是由JdkDynamicAopProxy产生的。

断点分析SimpleJpaRepository产生过程;

我们可以借鉴spring源码解读过程,通过AbstractApplicationContext的refresh方法查找细节;

进入断点查找线索

我们查找到beanName为resumeDao,点击下一步时发现他是 FactoryBean,并且 FactoryBean的类型是 JpaRepositoryFactoryBean;

读过spring源码的人都知道,factoryBean里面是有个getObject方法,它会产生一个具体的对象;

为什么会给它指定为 JpaRepositoryFactoryBean 呢?并且指定这个 FactoryBean 是在什么时候发生的呢?

我们着重分析一下是如何传入一个 resumeDao 就返回一个已经指定 classJpaRepositoryFactoryBeanBeanDefinition 对象的

上图 getMerGedLocalBeanDefinition 就有了,断点进入查看详情

我们可以看到是从map中获取的,那我们就看一下是什么时候put进去的;

此时定位到了一个方法在做这件事

观察这个方法的调用栈

我们发先 getMerGedLocalBeanDefinition 方法调用时 参数传进来的时候,这个BeanDefinition的class类型就已经被指定为 JpaRepositoryFactoryBean 了。我们需要观察该方法的调用栈;

回溯发现是在这一步通过beanName获取到了一个 Beandefinition,该 Beandefinition中的class是被指定为FactoryBean了;

我们在return处打断点重新走一遍,进入 getBeanDefinition 方法;

所有的bean被扫描处理之后,都进行注册,注册到该map中;

找到beanDefinitionMap.put关联方法,发现都在 registerBeanDefinition 中,向BeanDefinition中注入;

断点执行如下

发现传进来的时候就已经指定为 JpaRepositoryFactoryBean 了,继续回溯

解析jpa:respository标签过程,注意,这一步很重要!

进入该方法,

重点追踪该方法,BeanDefinition中class指定就发生在这里,我们debug进去该方法;

这一步执行之后,JpaRepositoryFactoryBean 就产生了,,,

debug进去rootBeanDefinition方法中

我们发现这个方法返回了一个固定的class类型,就叫做 JpaRepositoryFactoryBean;

通过上述追踪我们发现,其实在applicationContext.xml文件中,如下

<jpa:repositories base-package="com.yun.demo.dao" entity-manager-factory-ref="entityManagerFactory"
                transaction-manager-ref="transactionManager"/>

扫描到的接口,在进行BeanDefinition注册的时候,class会被固定的指定为 JpaRepositoryFactoryBean


追踪完JpaRepositoryFactoryBean,我们可以拓展一下 JpaRepositoryFactoryBean 是一个什么样的类;

我们重点关注一下factoryBean里面的getObject方法;

JpaRepositoryFactoryBean 爷爷类 RepositoryFactoryBeanSupport 中找到了getObject方法;

getObject方法里面我们查看一下this.repository.get()是如何赋值的;

JpaRepositoryFactoryBean 的爷爷类中初始化方法完成了对 repository 变量的赋值;repository 这个变量里面持有了我们需要的对象,而且这个对象它是一个代理对象

研究过过spring bean生命周期的应该知道,afterPropertiesSet 方法是初始化之后调用的方法,如下,实现了InitializingBean接口,

在return处打上断点,我们进去,查看是是如何产生代理对象并且赋值的,

如上图 information生成这一步,指定了要产生的代理对象类型是SimpleJpaRepository;

重新debug进入标记的方法,看看它是怎么指定的;

上图操作,baseClass该类型就是SimpleJpaRepository,直接进入该方法查看详情;

搞了半天,代理对象类型固定为了 SimpleJpaRepository(和 JpaRepositoryFactoryBean 获取方式一样)

要借助代理对象工厂产生代理对象

获取代理对象

选择使用JDK动态代理!

我们看一下JdkDynamicAopProxy结构

类中有一个方法可以产生代理对象,而增强的也正是自己,说明当前类应该是实现了InvocationHandler接口,当前类中应该也有一个Invoke方法;

如图!由此可见,JDK动态代理会生成一个类型为 SimpleJpaRepository 的代理对象,而该对象的增强逻辑就在 JdkDynamicAopProxy类的Invoke方法中.

我点击 SimpleJpaRepository 发现一个好玩的事情,如下图

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

呕吼,找到根了,方法实现调用了jpa原本的api;

SpringDataJpa源码理解的更多相关文章

  1. Caffe源码理解2:SyncedMemory CPU和GPU间的数据同步

    目录 写在前面 成员变量的含义及作用 构造与析构 内存同步管理 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 在Caffe源码理解1中介绍了Blob类,其中的数据成 ...

  2. 基于SpringBoot的Environment源码理解实现分散配置

    前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...

  3. jedis的源码理解-基础篇

    [jedis的源码理解-基础篇][http://my.oschina.net/u/944165/blog/127998] (关注实现关键功能的类)   基于jedis 2.2.0-SNAPSHOT   ...

  4. spring-data-JPA源码解读

    spring-data-JPA源码部分有两个很重要的部分:1.识别repositories接口 2.将接口添加代理实现类并托管spring管理 JpaRepositoriesRegistrar 目的是 ...

  5. VUEJS2.0源码理解--优

    VUEJS2.0源码理解 http://jiongks.name/blog/vue-code-review/#pingback-112428

  6. AdvanceEast源码理解

    目录 文章思路 源码理解 一. 标签点形式 按顺序排列四个点,逆时针旋转,且第一个点为左上角点(刚开始选择最左边的点, 二. 标签切边 三. loss计算 四. NMS 最后说明 文章思路 大神的gi ...

  7. Pytorch学习之源码理解:pytorch/examples/mnists

    Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...

  8. .NET Core 3.0之深入源码理解Startup的注册及运行

    原文:.NET Core 3.0之深入源码理解Startup的注册及运行   写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程 ...

  9. 深入源码理解Spring整合MyBatis原理

    写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...

  10. HashMap源码理解一下?

    HashMap 是一个散列桶(本质是数组+链表),散列桶就是数据结构里面的散列表,每个数组元素是一个Node节点,该节点又链接着多个节点形成一个链表,故一个数组元素 = 一个链表,利用了数组线性查找和 ...

随机推荐

  1. Openstack Neutron : LBaaS v2

    目录 - LBaaS v2 - 负载均衡概念 - 服务器池 Pool - 监听器 Listener - L7 转发策略 l7 policy - 负载均衡算法 Algorithms - 健康监测 Mon ...

  2. 安装配置docker&maven环境

     原文视频:(https://blog.sechelper.com/20220919/code-review/docker-maven-install-guid/) Docker是什么 Docker ...

  3. .NET 6当中的Web API版本控制

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 为了了解ASP.NET Core Web API的版本控制,我们必须了解API中的 ...

  4. 学习完nio的一个小笔记吧

    这是一个nio网络通信服务端的demo,主要就学习了selector的一些用法,以及它里面的事件类型 selector是对nio的一个优化,它能保证既能高效处理线程中的事件,又能保证线程不会一直占用c ...

  5. 第六章:Django 综合篇 - 14:Django 日志

    Django使用Python内置的logging模块实现它自己的日志系统. 如果你没有使用过logging模块,请参考Python教程中的相关章节. 直达链接<logging模块详解>. ...

  6. 解决RHEL7.3系统找不到yum命令,无法使用YUM源的问题

    前言 RHEL的YUM源需要注册用户才能更新使用,由于CentOS和RHEL基本没有区别,并且CentOS已经被REHL收购.所以将RHEL的YUM源替换为CentOS即可. [root@NISEC- ...

  7. NAT模式下的虚拟机连接主机网络

    基于NAT模式的VMware虚拟机(Linux CentOS 7)连接主机(Windows 11)网络 一.什么是NAT模式 虚拟机连接主机网络的三种方式: Bridged(桥接) NAT(网络地址转 ...

  8. Python实现给图片加水印功能

    前言 最近忙得连轴转,很久没更新博客了,代码倒是没啥写,积累了好些东西,接下来一有时间就来更新吧~ 本文记录使用Python实现给图片添加水印的功能实现过程 先看效果 把公众号的封面作为素材 原图是这 ...

  9. 谣言检测(RDEA)《Rumor Detection on Social Media with Event Augmentations》

    论文信息 论文标题:Rumor Detection on Social Media with Event Augmentations论文作者:Zhenyu He, Ce Li, Fan Zhou, Y ...

  10. Spring Boot 配置 jar 包外面的 Properties 配置文件

    一.概述 Properties 文件是我们可以用来存储项目特定信息的常用方法.理想情况下,我们应该将其保留在 jar 包之外,以便能够根据需要对配置进行更改. 在这个教程中,我们将研究在 Spring ...