首页 > 编程语言 >SpringDataJpa源码理解

SpringDataJpa源码理解

时间:2022-11-25 17:57:21浏览次数:37  
标签:SpringDataJpa 对象 理解 代理 JpaRepositoryFactoryBean 源码 方法 SimpleJpaRepository

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,对象,理解,代理,JpaRepositoryFactoryBean,源码,方法,SimpleJpaRepository
From: https://www.cnblogs.com/wangshaoyun/p/16925905.html

相关文章

  • go源码学习(零):前置知识-编译过程
    编译原理-从源码到机器码任何一门高级语言,要想最终能够在机器上执行那么就一定要从源码生成机器码,因为对于机器来说,它只认同由0和1组成的二进制程序。从人类可读的源码到......
  • Dubbo源码-05-服务导出
    一入口驱动publicstaticvoidmain(String[]args)throwsIOException{//服务提供者暴露服务配置封装了与注册中心的连接ServiceConfig<DemoServ......
  • Dubbo源码-06-ProxyFactory
    作用生产者将要导出的目标对象封装(代理技术或者反射技术)成Invoker对象一接口@SPI("javassist")publicinterfaceProxyFactory{/***createproxy.......
  • Dubbo源码-07-Protocol
    作用生产者将Invoker对象导出InjvmProtocol没有真正的干活逻辑仅仅是一些属性赋值DubboProtol启动服务RegistryProtol通过DubboProtocol启动服务注册远程配置......
  • SpringBoot原理深入及源码剖析
    1依赖管理问题:(1)为什么导入dependency时不需要指定版本?在SpringBoot入门程序中,项目pom.xml文件有两个核心依赖,分别是spring-boot-starter-parent和spring-boot-starter-w......
  • 4-4 child_process 库源码分析
    疑问和收获exec和execFile到底有什么区别?为什么exec/execFile/fork都是通过spawn实现的,spawn的作用到底是什么?为什么spawn调用后没有回调,而exec和......
  • matlab工具箱TTSBOX源码中文分析
    functionwav=tts(txt,voice,pace,fs)%TTStexttospeech.%TTS(TXT)synthesizesspeechfromstringTXT,andspeaksit.Theaudio%formatismono,16bit,1......
  • 【iOS-Cocos2d游戏开发之十五】详解CCProgressTimer 进度条并修改cocos2d源码实现“理
    ​​ 李华明Himi ​​​原创,转载务必在明显处注明     游戏开发中难免用到进度条,例如做一些游戏技能的CD时间等都会使用到;那么cocos2d当然也封装了进度条,但是不......
  • 手机直播源码,flutter 随机数的生成和保留两位小数
    手机直播源码,flutter随机数的生成和保留两位小数一、生成最小值和最大值之间的随机数使用Random().nextInt()方法,生成一个整数 random(min,max){ //+min 表......
  • 视频直播系统源码,flutter Wrap 自动换行组件
    视频直播系统源码,flutterWrap自动换行组件 先来简单的看一下源码 Wrap({  super.key,  this.direction=Axis.horizontal,  this.alignment=WrapAl......