Spring之AOP源碼解析(中)

前言

在上一篇文章中,我們講解了Spring中那些注解可能會產生AOP動態代理,我們通過源碼發現,完成AOP相關操作都和ProxyFactory這個類有密切關系,這一篇我們將圍繞這個類繼續解析

演示

作用

ProxyFactory采用策略模式生成動態代理對象,具體生成cglib動態代理還是jdk動態代理,是根據我們具體設置的內容所決定的,我們分別演示一下生成cglib動態代理和jdk動態代理兩種情況。具體細節可以詳細閱讀DefaultAopProxyFactory的createAopProxy方法

生成cglib動態代理

package com.test.aop.test;public class CglibTarget {public void doObject() {System.out.println("CglibTarget doObject");}
}
package com.test.aop.test;import org.springframework.aop.framework.ProxyFactory;public class CglibProxy {public static void main(String[] args) {ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setTarget(new CglibTarget());CglibTarget proxy = (CglibTarget) proxyFactory.getProxy();proxy.doObject();}
}

我們可以發現最終是以cglib動態代理方式生成代理對象

?生成jdk動態代理

package com.test.aop.test;public interface JdkTarget {void doObject();
}
package com.test.aop.test;public class JdkTargetImpl implements JdkTarget {@Overridepublic void doObject() {System.out.println("JdkTargetImpl doObject");}
}
package com.test.aop.test;import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.target.SingletonTargetSource;public class JdkProxy {public static void main(String[] args) {ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setInterfaces(JdkTarget.class);proxyFactory.setTargetSource(new SingletonTargetSource(new JdkTargetImpl()));JdkTarget proxy = (JdkTarget) proxyFactory.getProxy();proxy.doObject();}
}

我們可以發現最終是以jdk動態代理方式生成代理對象?

ProxyFactory源碼解析

我們先觀察一下ProxyFactory這個類的繼承關系

我們以proxyFactory.getProxy()方法為切入口,進行源碼解析?

對上述流程進行梳理,見下圖

我們分別查看兩種方式的代理過程

jdk動態代理過程(JdkDynamicAopProxy)

jdk動態代理的過程比較簡單主要就是利用Proxy.newProxyInstance方法創建代理對象,會默認實現SpringProxy,Advised,DecoratingProxy三個接口

cglib動態代理過程(CglibAopProxy)?

cglib動態代理主要利用我們自定義的ProxyFactory對象,然后根據設置的參數構建Enhancer對象,然后創建代理對象。我們需要注意的是代理對象一共有七個攔截器,spring會根據我們調用的方法,指定攔截器。比如我們調用equal方法就會經過EqualsInterceptor攔截器,調用hashCode方法就會經過HashCodeInterceptor攔截器。我們主要需要關注的就是DynamicAdvisedInterceptor攔截器,除了equal、hashcode這些特殊的方法,普通方法一般都會經過這個攔截器。具體進入那個攔截器可以查看CglibAopProxy類的accept方法

cglib動態代理的對象會默認實現SpringProxy,Advised兩個接口

ProxyFactory的重要屬性Advisor

我們在前文中說到@EnableTransactionManagement,@EnableAspectJAutoProxy完成AOP動態代理都是依靠AbstractAutoProxyCreator的postProcessAfterInitialization方法中完成的,其中最主要的方法是wrapIfNecessary,我們查看相關源碼

通過源碼我們知道只有找到了,可以作用于當前bean的Advisor,spring才會進行動態代理

我們在上文中提到了@EnableTransactionManagement,@EnableAspectJAutoProxy兩個注解的淵源,然后得出結論:如果同時存在,最終只能存在一個優先級更高的BeanPostProcessor(bpp)

那么@EnableAspectJAutoProxy這個注解注入了一個優先級更高的bpp,有什么擴展點呢?我們以上圖中getAdvicesAndAdvisorsForBean方法為切入口進行分析

@EnableTransactionManagement注入的bpp沒有重寫findCandidateAdvisors方法,其查找Advisor的方法為父類的默認實現。@EnableAspectJAutoProxy注解注入的bpp重寫了findCandidateAdvisors方法,其在父類方法的基礎上又試圖通過BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法尋找更多的Advisor,最后再判斷這些找到的Advisors是否可以作用在當前bean,如果存在可以作用于當前bean的Advisors,則進行AOP動態代理

?總結

ProxyFactory這個類在Spring完成AOP動態代理的過程中起到了重要的作用,具體如下所述

  • 可以通過配置決定Spring進行aop動態代理的方式,比如將@EnableTransactionManagement注解的proxyTargetClass參數設置為true(不能保證一定進行cglib動態代理,具體可以查看DefaultAopProxyFactory的createAopProxy方法)
  • 可以設置監聽器,監聽動態代理對象
  • 可以決定是否提前暴露代理對象,比如將@EnableAspectJAutoProxy注解的exposeProxy參數設置為true,然后通過AopContext.currentProxy()就可以獲取原始對象
  • 可以通過查找是否存在作用于指定bean的Advisors,來決定是否需要進行動態代理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/696889.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696889.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696889.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

算法提升——LeetCode第385場周賽總結

題目 統計前后綴下標對 I 給你一個下標從0開始的字符串數組words。 定義一個布爾函數isPrefixAndSuffix,它接受兩個字符串參數str1和str2: 當str1同時是str2的前綴(prefix)和后綴(suffix)時&#xff0c…

APP的UI自動化demo(appium+java)

文章目錄 appium連接手機java代碼實現-第一版第二版-接入testng和隱式等待顯示等待 appium連接手機 準備工作 1、查看連接手機模擬器是否連接成功,獲取設備名稱 執行命令:adb devices 2、查看android內核版本號—>paltformVersion 執行命令&#xf…

MQL語言實現單元測試

文章目錄 一、單元測試是什么二、單元測試的過程三、為什么需要單元測試四、MQL測試代碼實現 一、單元測試是什么 單元測試是對軟件中最小可測單元(如類或函數)進行獨立驗證和檢查的過程。它是由開發工程師完成的,旨在確保每個單元的功能和邏…

Postman接口關聯實戰解析

在使用postman做接口測試時,有時候后面的接口需要獲取前面接口的某一個返回值做為請求參數,這時就可以使用關聯。 如從A接口提取出a字段的值,供B接口的b字段使用。 一個接口的返回報文如下: {"retCode": "0&quo…

SwiftUI 集合視圖(Grid)拖放交換 Cell 的極簡實現

概覽 自從 SwiftUI 橫空出世那天起,小伙伴們都感受到了它驚人的簡單與便捷。而在本課中,我們將會用一個小“栗子”更直觀的讓大家體驗到它無與倫比簡潔的描述性特質: 如上圖所示,我們在 SwiftUI 中實現了 Grid 中拖放交換 Cell 的…

基于SpringBoot + Layui的社區物業管理系統

項目介紹 社區物業管理系統是基于java編程語言,springboot框架,idea工具,mysql數據庫進行開發,本系統分為業主和管理員兩個角色,業主可以登陸系統,查看車位費用信息,查看物業費用信息&#xff0…

2個wordpress優化SEO主題模板

SEO優化wordpress主題 簡潔的SEO優化wordpress主題,效果好不好,結果會告訴你,適合SEO公司使用的主題。 https://www.jianzhanpress.com/?p2804 SEO優化海外WordPress主題 簡潔的SEO優化海外服務商WordPress主題,為中國制造202…

C# byte[]、struct、intptr、byte[]和byte*等的相互轉換

struct、byte[]互相轉換 //struct轉換為byte[] public static byte[] StructToBytes(object structObj) {int size Marshal.SizeOf(structObj);IntPtr buffer Marshal.AllocHGlobal(size);try{Marshal.StructureToPtr(structObj, buffer, false);byte[] bytes new byte[siz…

HTTP REST 方式調用WebService接口(wsdl)

一、WebService接口正常使用SOAP協議調用,測試時常采用SoapUI軟件調用,具體如下: 二、由于目前主流web服務逐漸轉換為RESTful的形式,且SOAP協議的實現也是基于HTTP協議,故存在通過HTTP調用WebService接口的可能 2.1 …

Flink雙流(join)

一、介紹 Join大體分類只有兩種:Window Join和Interval Join Window Join有可以根據Window的類型細分出3種:Tumbling(滾動) Window Join、Sliding(滑動) Window Join、Session(會話) Widnow Join。 🌸Window 類型的join都是利用window的機制…

【OpenFeign常用配置】

OpenFeign常用配置 快速入門:1、引入依賴2、啟用OpenFeign 實踐1、引入依賴2、開啟連接池功能3、模塊劃分4、日志5、重試 快速入門: OpenFeign是一個聲明式的http客戶端,是spring cloud在eureka公司開源的feign基礎上改造而來。其作用及時基于…

C++ template-2

第 5 章 基礎技巧 5.1 typename 關鍵字 關鍵字typename在C標準化過程中被引入進來&#xff0c;用來澄清模板內部的一個標識符代表的 是某種類型&#xff0c;而不是數據成員。考慮下面這個例子&#xff1a; template<typename T> class MyClass { public:void foo() {t…

【代碼隨想錄算法訓練營Day09】28.實現 strStr(); 459.重復的子字符串

文章目錄 Day 9 第四章 字符串part0228. 實現 strStr() &#xff08;本題可以跳過&#xff09;KMP 思路KMP 代碼 459.重復的子字符串 &#xff08;本題可以跳過&#xff09;字符串總結雙指針回顧 Day 9 第四章 字符串part02 今日任務 28.實現 strStr(); 459.重復的子字符串; 字…

題目:C++快速找到未知長度單鏈表的中間節點。普通方法和高級方法2種解題思路解析。

在數據結構的面試中&#xff0c;經常會出現這樣的問題&#xff1a;如何快速找到未知長度單鏈表的中間節點&#xff1f;通常&#xff0c;面試官會期待你提供兩種解法&#xff1a;一種是最基本的普通方法&#xff0c;另一種是更高效的 advanced 方法。本文將詳細介紹這兩種方法。…

Nginx -2

接著上文寫 5.4.7 驗證模塊 需要輸入用戶名和密碼 模塊名稱&#xff1a;ngx_http_auth_basic_module 訪問控制基于模塊 ngx_http_auth_basic_module 實現&#xff0c;可以通過匹配客戶端資源進行限制 語法&#xff1a; Syntax: auth_basic string | off; Default: auth_ba…

威爾金森功分器基本原理學習筆記

威爾金森功分器基本原理 威爾金森功率分配器的功能是將輸入信號等分或不等分的分配到各個輸出端口&#xff0c;并保持相同輸出相位。環形器雖然有類似功能&#xff0c;但威爾金森功率分配器在應用上具有更寬的帶寬。微帶形功分器的電路結構如圖所示&#xff0c;其中&#xff0…

【OpenAI Sora】何時開放使用?付費課程已上線(sora什么時候開放使用 )

Sora何時開放使用 根據提供的信息&#xff0c;Sora目前還未對廣大用戶開放。OpenAI在2024年2月15日展示了Sora的視頻&#xff0c;但沒有設立等待名單或提供API訪問。Sora仍在開發中&#xff0c;正在接受安全測試&#xff0c;并且尚未向公眾開放使用。 付費課程已上線 根據最…

Vue圖片瀏覽組件v-viewer,支持旋轉、縮放、翻轉等操作

Vue圖片瀏覽組件v-viewer&#xff0c;支持旋轉、縮放、翻轉等操作 之前用過viewer.js&#xff0c;算是市場上用過最全面的圖片預覽。v-viewer&#xff0c;是基于viewer.js的一個圖片瀏覽的Vue組件&#xff0c;支持旋轉、縮放、翻轉等操作。 基本使用 安裝&#xff1a;npm安裝…

費舍爾FISHER金屬探測器探測儀維修F70

美國FISHER LABS費舍爾地下金屬探測器&#xff0c;金屬探測儀等維修&#xff08;考古探金銀銅探寶等儀器&#xff09;。 費舍爾F70視聽目標ID金屬探測器&#xff0c;Fisher 金屬探測器公司成立于1931年&#xff0c;在實驗條件很艱苦的情況下&#xff0c;研發出了地下金屬探測器…

【Python】實現一個類似于Glass2k的Windows窗口透明化軟件

一 背景說明 網上看到一款Windows下的窗口透明化工具Glass2k&#xff08;Glass2k官網&#xff09;&#xff0c;可以簡單地通過快捷鍵實現任意窗口的透明化&#xff0c;還挺方便的&#xff0c;想用Python自己實現一下類似的功能。 軟件已經開源到&#xff1a;窗口透明化小工具開…