SpringDataJpa源码理解
SpringDataJpa源码理解
上一篇讲解了SpringDataJpa的基本使用,下面简单说一下源码
我们以其中的一个test为案例进行分析:
我们可以发现resumeDao它是一个代理对象,类型是SimpleJpaRepository,是由JdkDynamicAopProxy产生的。
断点分析SimpleJpaRepository产生过程;
我们可以借鉴spring源码解读过程,通过AbstractApplicationContext的refresh方法查找细节;
进入断点查找线索
我们查找到beanName为resumeDao,点击下一步时发现他是 FactoryBean,并且 FactoryBean的类型是 JpaRepositoryFactoryBean;
读过spring源码的人都知道,factoryBean里面是有个getObject方法,它会产生一个具体的对象;
为什么会给它指定为 JpaRepositoryFactoryBean 呢?并且指定这个 FactoryBean 是在什么时候发生的呢?
我们着重分析一下是如何传入一个 resumeDao 就返回一个已经指定 class 为 JpaRepositoryFactoryBean 的 BeanDefinition 对象的
上图 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源码理解的更多相关文章
- Caffe源码理解2:SyncedMemory CPU和GPU间的数据同步
目录 写在前面 成员变量的含义及作用 构造与析构 内存同步管理 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 在Caffe源码理解1中介绍了Blob类,其中的数据成 ...
- 基于SpringBoot的Environment源码理解实现分散配置
前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...
- jedis的源码理解-基础篇
[jedis的源码理解-基础篇][http://my.oschina.net/u/944165/blog/127998] (关注实现关键功能的类) 基于jedis 2.2.0-SNAPSHOT ...
- spring-data-JPA源码解读
spring-data-JPA源码部分有两个很重要的部分:1.识别repositories接口 2.将接口添加代理实现类并托管spring管理 JpaRepositoriesRegistrar 目的是 ...
- VUEJS2.0源码理解--优
VUEJS2.0源码理解 http://jiongks.name/blog/vue-code-review/#pingback-112428
- AdvanceEast源码理解
目录 文章思路 源码理解 一. 标签点形式 按顺序排列四个点,逆时针旋转,且第一个点为左上角点(刚开始选择最左边的点, 二. 标签切边 三. loss计算 四. NMS 最后说明 文章思路 大神的gi ...
- Pytorch学习之源码理解:pytorch/examples/mnists
Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...
- .NET Core 3.0之深入源码理解Startup的注册及运行
原文:.NET Core 3.0之深入源码理解Startup的注册及运行 写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程 ...
- 深入源码理解Spring整合MyBatis原理
写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...
- HashMap源码理解一下?
HashMap 是一个散列桶(本质是数组+链表),散列桶就是数据结构里面的散列表,每个数组元素是一个Node节点,该节点又链接着多个节点形成一个链表,故一个数组元素 = 一个链表,利用了数组线性查找和 ...
随机推荐
- 2_CSS
1. 什么是CSS 1.1 什么是CSS Cascading Style Sheet 层叠样式表 是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的 ...
- C#-11 接口
一 什么是接口 接口是指定一组函数成员而不实现它们的引用类型. class Program { static void FlyFunc(IFly obj) { obj.Fly(); } static ...
- JavaScript之无题之让人烦躁的模块化
我怎么记得我好像写过相关类型的文章,但是我找遍了我的博客没有-那就再写一遍吧,其实模块化的核心内容也算不上是复杂,只不过需要整理一下,规划一下罢了.嘻嘻. 开始写标题的时候我就在纠结一件事情,就是,先 ...
- 微信DAT文件转JPG图片(图片恢复)
微信电脑版现在已经是日常工作生活必不可少的工具,有时候删除了聊天记录或者被系统清理软件清理了,但还想查看曾经的微信聊天图片. 这个时候辛辛苦苦找到了文件,却发现无法查看,因为微信电脑版为了保护我们的隐 ...
- 前端ajax发送post 请求 json格式 springMVC报错415
如标题所示 后端填坑日记 在使用springMVC的时候发现 后端使用@RequestBody注解会报错415 不支持的媒体类型 相信很多小伙伴都遇到过或者正在面临这个报错 提示错误:The serv ...
- MasaFramework -- 异常处理
前言 在程序设计中,我们会遇到各种各样的异常问题,一个异常处理不仅仅可以帮助开发者快速的定位问题,也可以给用户更好的使用体验,那么我们在AspNetCore项目中如何捕获以及处理异常呢? 而对应Asp ...
- Linux中CentOS 7版本安装JDK、Tomcat、MySQL、lezsz、maven软件详解
软件安装 在Linux系统中,安装软件的方式主要有四种,这四种安装方式的特点如下: 安装方式 特点 二进制发布包安装 软件已经针对具体平台编译打包发布,只要解压,修改配置即可 rpm安装 软件已经按照 ...
- IDEA生成带参数和返回值注释
步骤说明 打开IDEA进入点击左上角 - 文件 - 设置 - 编辑器 - 活动模板 新建活动模板 填写模板文本 编辑变量 添加变量表达式 设置模板使用范围-设置全部范围应用-或者设置只在Java代码中 ...
- NVIDIA Isaac Gym安装与使用
NVIDIA做的Isaac Gym,个人理解就是一个类似于openai的Gym,不过把环境的模拟这个部分扔到了GPU上进行,这样可以提升RL训练的速度. 官网:https://developer.nv ...
- Response对象页面重定向、时间的动态显示
Response对象 response对象主要用于对客户端的请求进行回应,将web服务器处理后的结果发回给客户端,封装了jsp产生的响应,并发送到客户端响应客户端的请求,请求的数据可以是各种数据类型, ...