我的架構夢:(十二)Spring Data JPA 源碼分析

一、前言

Spring Data JPA 源碼很少有人去分析,原因如下:

1、Spring Data JPA 地位沒有之前學習的框架高,大家習慣把它當成一個工具來用了,不願意對它進行源碼層次的解讀。

2、開發Dao接口(ResumeDao),接口的實現對象肯定是通過動態代理來完成的(增強),代理對象的產生過程追源碼很難追,特別特別講究技巧。

這裏,我來和大家一起分析下源碼,Spring Data JPA源碼剖析的主要的過程,就是代理對象產生的過程。

我們發現resumeDao是一個代理對象,這個代理對象的類型是SimpleJapRepository。代理對象在h裏產生。

在這裏插入圖片描述

二、這個代理對象是怎麼產生,過程是怎樣的?

以往:如果要給一個對象產生代理對象,我們知道是在AbstractApplicationContextrefresh方法中, 那麼能不能在這個方法中找到什麼我們當前場景的線索?

在這裏插入圖片描述

在這裏插入圖片描述

進入該方法以後,斷點到這一行,輸入beanName.equals("resumeDao")

在這裏插入圖片描述

在這裏插入圖片描述

新的疑問又來了?

問題1: 爲什麼會給它指定爲一個JpaRespositoryFactoryBean#getObject方法返回具體的對象?

問題2:指定這個FactoryBean是在什麼時候發生的?

首先解決問題2:

在這裏插入圖片描述

傳入一個resumeDao就返回了一個已經指定classJpaRepositoryFactoryBeanBeanDefinition對象了,那麼應該在上圖中的get時候就有了,所以斷點進入:

private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap(256);

在這裏插入圖片描述

問題來了,什麼時候putmap中去的?我們定位到了一個方法在做這件事:

mergedBeanDefinitions.put Find Usages 反調找到該方法:

在這裏插入圖片描述

在這裏插入圖片描述
我們發現,傳入該方法的時候,BeanDefintion中的class就已經被指定爲FactoryBean了,那麼觀察該方法的調用棧。

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
繼續跟進,發現 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configuration.getRepositoryFactoryBeanClassName());這行代碼已經產生了JpaRepositoryFactoryBean
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

通過上述追蹤我們發現,<jpa:repository basePackage,掃描到的接口,在進行BeanDefintion 註冊時候,class會被固定的指定爲JpaRepositoryFacotryBean

至此,問題2 追蹤完畢。


那麼接下來,我們再來追蹤問題1 JpaRespositoryFactoryBean是一個什麼樣的類,它是一個FactoryBean,我們重點關注FactoryBeangetObject方法。

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

由此可⻅,JdkDynamicAopProxy會生成一個代理對象類型爲SimpleJpaRespository,而該對象的增強邏輯就在JdkDynamicAopProxy類的invoke方法中。

至此,問題1追蹤完畢。

三、這個代理對象類型SimpleJpaRepository有什麼特別的?

在這裏插入圖片描述

在這裏插入圖片描述

原來SimpleJpaRepository類實現了JpaRepository接口和JpaSpecificationExecutor接口。

在這裏插入圖片描述

Spring Data JPA 級別的封裝也就到這了,剩下的是JPAhibernate的源碼了,這也印證了我們剛開始講的Spring Data JPA是對JPA的高級封裝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章