Spring之AOP源碼解析(上)

Aop相關注解

  • @EnableTransactionManagement
  • @EnableAspectJAutoProxy
  • @EnableAsync
  • ...

從注解切入來看看這些注解都干了什么

@Import注解作用簡述

注入的類一般繼承ImportSelector或者ImportBeanDefinitionRegistrar接口

  • 繼承ImportSelector接口:selectImports方法返回的類名會被解析成bean
  • 繼承ImportBeanDefinitionRegistrar接口:會在解析階段執行registerBeanDefinitions方法

Spring解析流程可以看我之前寫的博文 《Spring之ConfigurationClassPostProcessor解析流程》重點講解了@Import等注解是如何解析的

@EnableAsync注解

@EnableAsync注解作用
  • 注入一個類型為AsyncAnnotationBeanPostProcessor的BeanPostProcessor

@EnableTransactionManagement注解

@EnableTransactionManagement注解作用
  • 注入一個類型為InfrastructureAdvisorAutoProxyCreator的BeanPostProcessor
  • 注入事務相關的bean

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解作用
  • 注入一個類型為AnnotationAwareAspectJAutoProxyCreator的bpp

@EnableTransactionManagement和@EnableAspectJAutoProxy注解的淵源

從方法的角度

兩個類都是通過AopConfigUtils.registerXXX方法注入一個bpp到spring中

注意點:AopConfigUtils的register方法存在三個優先級,如果spring調用了多次register方法,spring會保留優先級最高的bpp(beanName為org.springframework.aop.config.internalAutoProxyCreator)。比如Spring中同時存在@EnableTransactionManagement和@EnableAspectJAutoProxy注解,但因為@EnableAspectJAutoProxy注解注入的bpp的優先級高于@EnableTransactionManagement注解注入的bpp,所以spring只有一個類型為AnnotationAwareAspectJAutoProxyCreator的bean,而不存在類型為InfrastructureAdvisorAutoProxyCreator的bean

相關源碼AopConfigUtils#registerOrEscalateApcAsRequired

從類的的角度

兩個bpp都繼承AbstractAutoProxyCreator,然而Spring動態代理相關的邏輯都是在這個類中處理的,所有我們可以認為@EnableTransactionManagement和@EnableAspectJAutoProxy注解實現動態代理的邏輯是一樣的。

注解實現動態代理的時機

@EnableAsync注解

我們從前文中了解到@EnableAsync注解會注入一個類型為AsyncAnnotationBeanPostProcessor的bpp,我們來查看源碼

我們通過類的繼承關系,關注其祖父類(AbstractAdvisingBeanPostProcessor)的postProcessAfterInitialization方法

@EnableTransactionManagement和@EnableAspectJAutoProxy注解

通過上文的分析,我們主要查看AbstractAutoProxyCreator的postProcessAfterInitialization方法

通過源碼,我們得出以下幾個結論

  • 幾個注解注入的bpp都是通過postProcessAfterInitialization方法進行動態代理
  • Spring是通過ProxyFactory這個類完成動態代理的

Spring是如何解決多個bpp對bean進行處理的順序問題

我們回過頭查看@EnableAsync注解注入的bpp的postProcessAfterInitialization方法

從碼義上來說,@EnableAsync注解進行AOP動態代理優先級是比較低的,那Spring是怎么處理,讓優先級比較低的bpp稍后執行呢?

我們查看源碼PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

Spring會對所有的bpp進行排序,然后按順序加入到列表中,優先級較高的優先加入,優先處理

這里的比較器使用的是AnnotationAwareOrderComparator,這個比較器大致分成以下步驟

  1. bpp是否繼承PriorityOrdered接口,如果都繼承PriorityOrdered接口,比較getOrder方法返回的值,值越小,優先級越高
  2. bpp是否繼承Ordered接口,如果都繼承Ordered接口,比較getOrder方法返回的值,值越小,優先級越高
  3. bpp所屬class上是否存在@Order注解,如果存在,比較@Order注解設置的值,值越小,優先級越高
  4. 其他

這里需要注意的是,如果一個bpp繼承PriorityOrdered接口,getOrder方法返回的值為100,另外一個bpp繼承Ordered接口,getOrder方法返回的值為1,按照第一優先級規則,還是繼承PriorityOrdered接口的bpp優先級高

我們查看三個注解相關源碼

@EnableAsync注解order默認值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)

@EnableTransactionManagement注解order默認值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)

@EnableAspectJAutoProxy注解未開啟設置

默認的情況下,@EnableAsync和@EnableTransactionManagement注解注入的bpp都繼承Ordered接口,并且getOrder方法返回的值都是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),默認情況下優先級一致,但是@EnableTransactionManagement注解注入bpp的時候,對order值進行了手動設置,保證了如果同時存在@EnableAsync和@EnableTransactionManagement注解的情況下,@EnableTransactionManagement注解注入的bpp進行AOP動態代理,@EnableAsync注解注入的bpp進行增強。如果只存在@EnableAsync注解,則相關bpp進行AOP動態代理

相關源碼AopConfigUtils#registerOrEscalateApcAsRequired

這里需要說明一下,雖然@EnableAspectJAutoProxy注解不能指定order值,但是有默認值,默認值也是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),@EnableTransactionManagement和@EnableAspectJAutoProxy注解從一定程度上來說,這些可以指定的參數是互補的,因為它們進行AOP動態代理的是操作是通過共同父類AbstractAutoProxyCreator完成的

總結

  • @EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableAsync注解都有可能產生AOP動態代理
  • @EnableTransactionManagement,@EnableAspectJAutoProxy注解注入的bpp,都是依靠AbstractAutoProxyCreator這個類完成動態代理的。如果它們同時存在,Spring中只會存在一個優先級更高的bpp。這兩個注解指定的參數是互補的,對于特定需求,可以進行擴展
  • 幾個注解注入的bpp,都是Spring執行到postProcessAfterInitialization方法階段,完成AOP動態代理
  • Spring通過registerOrEscalateApcAsRequired方法手動修改了@EnableTransactionManagement,@EnableAspectJAutoProxy注入的bpp的order值,所以執行順序優先于@EnableAsync注入的bpp
  • 幾個注解都是通過ProxyFactory這個類,以策略模式完成AOP動態代理(我們下一篇文章將重點講解這個類)

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

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

相關文章

pandas/geopandas 筆記:判斷地點在不在路網上 不在路網的點和路網的距離

0 導入庫 import osimport pandas as pd pd.set_option(display.max_rows,5)import osmnx as oximport geopandas as gpd from shapely.geometry import Point 1 讀取數據 假設我們有 如下的數據: 1.1 新加坡室外基站位置數據 cell_stationpd.read_csv(outdoor…

TSINGSEE青犀AI智能分析網關V4初始配置與算法相關配置介紹

TSINGSEE青犀AI智能分析網關V4內置了近40種AI算法模型,支持對接入的視頻圖像進行人、車、物、行為等實時檢測分析,上報識別結果,并能進行語音告警播放。硬件管理平臺支持RTSP、GB28181協議、以及廠家私有協議接入,可兼容市面上常見…

通過例子學習golang的Goroutine

Go 語言中的 Goroutine 是一種輕量級的并發執行單位。它可以與其他 Goroutine 并發地執行,而不需要顯式地管理線程的創建和銷毀。Goroutine 是 Go 語言并發模型的核心組成部分,它使得編寫并發程序變得更加簡單和高效。 例一 創建兩個function&#xff0…

linux下ffmpeg調用GPU硬件解碼(VDPAU/VAAPI)保存文件

本文講解在linux下面,如何通過ffmpeg調用GPU硬件解碼,并保存解碼完的yuv文件。 其實,ffmpeg自帶的例子hw_decode.c這個文件,就已經能滿足要求了,因此,本文就嘗試講解以下hw_decode這個例子。hw_decode.c可以…

watchpoint

前言 內存被踩,通過 watchpoint 找到真兇 實例 以 smsc911x 網卡驅動為基體,進行實驗,和網卡本身功能無關, 每執行一次 ifconfig eth0 up,就會調用一次 smsc911x_open(),我在這里設計了一段代碼&#xf…

數學知識(四)(容斥原理、博弈論)

一、容斥原理 容斥原理公式 一共加或者減的式子個數 (一)利用容斥原理解決求能被質數整除的數的個數 890計算能被整除的數的個數 因為一共有2^n-1種選法,可以用位運算的方式枚舉,對于得到的每一種選法,根據存在的數…

六、回歸與聚類算法 - 邏輯回歸與二分類

線性回歸欠擬合與過擬合線性回歸的改進 - 嶺回歸分類算法:邏輯回歸模型保存與加載無監督學習:K-means算法 1、應用場景 2、原理 2.1 輸入 2.2 激活函數 3、損失以及優化 3.1 損失 3.2 優化 4、邏輯回歸API 5、分類的評估方法 5.1 精確率和召回率 5.2…

找出作弊的人

文章目錄 題目描述輸入描述輸出描述樣例1解釋:樣例2代碼 題目描述 公司組織了一次考試,現在考試結果出來了,想看一下有沒人存在作弊行為,但是員工太多了,需要先對員工進行一次過濾,再進一步確定是否存在作弊行為。 過濾的規則為:找到分差最小的員工ID對(p1,p2)列表…

【Spring】IoC容器 控制反轉 與 DI依賴注入 配置類實現版本 第四期

文章目錄 基于 配置類 方式管理 Bean一、 配置類和掃描注解二、Bean定義組件三、高級特性:Bean注解細節四、高級特性:Import擴展五、基于注解配置類方式整合三層架構組件總結 基于 配置類 方式管理 Bean Spring 完全注解配置(Fully Annotatio…

Kotlin學習 6

1.接口 interface Movable {var maxSpeed: Intvar wheels: Intfun move(movable: Movable): String}class Car(var name: String, override var wheels: Int 4, _maxSpeed: Int) : Movable {override var maxSpeed: Int _maxSpeedget() fieldset(value) {field value}overr…

C語言讀取 ini 配置文件,修改/添加鍵值對

C語言讀取 ini 配置文件,修改/添加鍵值對 C語言讀取 ini 配置文件,對section中的鍵值對進行修改/添加,如果section不存在,則在末尾將新的section/key/value 添加進去。 一、了解什么是INI文件? ini 文件是Initializ…

【大數據】Flink 之部署篇

Flink 之部署篇 1.概述和參考架構2.可重復的資源清理3.部署模式3.1 Application 模式3.2 Per-Job 模式(已廢棄)3.3 Session 模式 Flink 是一個多用途框架,支持多種不同的混合部署方案。下面,我們將簡要介紹 Flink 集群的構建模塊、…

流動資金貸款管理辦法

流動資金貸款管理辦法 (2024年1月30日國家金融監督管理總局令2024年第2號公布 自2024年7月1日起施行) 第一章 總 則 第一條 為規范銀行業金融機構流動資金貸款業務經營行為,加強流動資金貸款審慎經營管理,促進流動資金貸款業務健康發展,依…

【html學習筆記】3.表單元素

1.文本框 1.1 語法 <input type "text">表示文本框。且只能寫一行 1.2 屬性 使用屬性size 設置文本框大小 <input type"text" size"10">2. 使用屬性value 來設置文本框的默認文字 <input type"text" size"…

Vue狀態管理庫-Pinia

一、Pinia是什么&#xff1f; Pinia 是 Vue 的專屬狀態管理庫&#xff0c;它允許支持跨組件或頁面共享狀態&#xff0c;即共享數據&#xff0c;他的初始設計目的是設計一個支持組合式API的 Vue 狀態管理庫&#xff08;因為vue3一個很大的改變就是組合式API&#xff09;,當然這…

PFA三角燒瓶實驗室PFA錐形瓶本底純凈耐腐蝕性強

PFA三角燒瓶外觀呈平底圓錐狀&#xff0c;下闊上狹&#xff0c;有一圓柱形頸部&#xff0c;上方有一較頸部闊的開口&#xff0c;可用塞子封閉。PFA三角燒瓶也稱PFA錐形瓶&#xff0c;PFA反應瓶&#xff0c;PFA三角燒瓶、PFA依氏燒瓶、PFA錐形燒瓶&#xff0c;PFA鄂倫麥爾瓶等。…

普中51單片機學習(串口通信)

串口通信 原理 計算機通信是將計算機技術和通信技術的相結合&#xff0c;完成計算機與外部設備或計算機與計算機之間的信息交換 。可以分為兩大類&#xff1a;并行通信與串行通信。并行通信通常是將數據字節的各位用多條數據線同時進行傳送 。控制簡單、傳輸速度快&#xff1…

【大模型】finetune 百川2

使用官網例子finetune百川2&#xff0c;微調腳本如下 模型為baichuan_chat_13B_v1 export CUDA_VISIBLE_DEVICES1 hostfile"" deepspeed --hostfile$hostfile baichuan_fineturn/fine-tune/fine-tune.py \--report_to "none" \--data_path "baichu…

2.22號qt

1.使用信號和槽實現多個界面跳轉 1.1準備兩個界面 1.2第一個界面準備signal 1.3第二個界面準備slot 1.4將第一個界面的信號和槽進行連接 2.qss登錄界面升級優化 2.1概念 Qss是Qt程序界面中用來設置控件的背景圖片、大小、字體顏色、字體類型、按鈕狀態變化等屬性&#xff…

【Python】Python實現串口通信(Python+Stm32)

&#x1f389;歡迎來到Python專欄~Python實現串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏與酒&#x1f379; ?博客主頁&#xff1a;小夏與酒的博客 &#x1f388;該系列文章專欄&#xff1a;Python學習專欄 文章作者技術和水平有限&#xff0c;如果文中出現錯誤&#xff0c;希望…