日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Spring AOP 超详细源码解析

發(fā)布時(shí)間:2023/12/20 javascript 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring AOP 超详细源码解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

知識(shí)章節(jié)

基礎(chǔ)知識(shí)

什么是 AOP

  • AOP 的全稱(chēng)是 “Aspect Oriented Programming”,即面向切面編程
  • 在 AOP 的思想里面,周邊功能(比如性能統(tǒng)計(jì),日志,事務(wù)管理等)被定義為切面,核心功能和切面功能分別獨(dú)立進(jìn)行開(kāi)發(fā),然后把核心功能和切面功能“編織”在一起,這就叫 AOP
  • AOP 能夠?qū)⒛切┡c業(yè)務(wù)無(wú)關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯封裝起來(lái),便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來(lái)的可拓展性和可維護(hù)性

AOP 基礎(chǔ)概念

  • 連接點(diǎn)(Join point):能夠被攔截的地方,Spring AOP 是基于動(dòng)態(tài)代理的,所以是方法攔截的,每個(gè)成員方法都可以稱(chēng)之為連接點(diǎn)
  • 切點(diǎn)(Poincut):每個(gè)方法都可以稱(chēng)之為連接點(diǎn),我們具體定位到某一個(gè)方法就成為切點(diǎn)
  • 增強(qiáng)/通知(Advice):表示添加到切點(diǎn)的一段邏輯代碼,并定位連接點(diǎn)的方位信息,簡(jiǎn)單來(lái)說(shuō)就定義了是干什么的,具體是在哪干
  • 織入(Weaving):將增強(qiáng)/通知添加到目標(biāo)類(lèi)的具體連接點(diǎn)上的過(guò)程
  • 引入/引介(Introduction):允許我們向現(xiàn)有的類(lèi)添加新方法或?qū)傩?#xff0c;是一種特殊的增強(qiáng)
  • 切面(Aspect):切面由切點(diǎn)和增強(qiáng)/通知組成,它既包括了橫切邏輯的定義、也包括了連接點(diǎn)的定義。

  • AOP 五種通知分類(lèi)
    • 前置通知(Before Advice):在目標(biāo)方法被調(diào)用前調(diào)用通知功能
    • 后置通知(After Advice):在目標(biāo)方法被調(diào)用之后調(diào)用通知功能
    • 返回通知(After-returning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知功能
    • 異常通知(After-throwing):在目標(biāo)方法拋出異常之后調(diào)用通知功能
    • 環(huán)繞通知(Around):把整個(gè)目標(biāo)方法包裹起來(lái),在被調(diào)用前和調(diào)用之后分別調(diào)用通知功能

AOP 簡(jiǎn)單示例

創(chuàng)建一個(gè)配置類(lèi),開(kāi)啟 AspectJ 的自動(dòng)代理功能

@Configuration @EnableAspectJAutoProxy @ComponentScan("com.aspectj") public class DemoAspectJConfig {// @EnableAspectJAutoProxy 開(kāi)啟注解 aop 功能// 向 spring 容器中注冊(cè) AnnotationAwareAspectJAutoProxyCreator }

新建接口和接口實(shí)現(xiàn)類(lèi)

// 接口 public interface DemoDao {void query(); }// 實(shí)現(xiàn)類(lèi) @Component public class DemoDaoImpl implements DemoDao {@Overridepublic void query() {System.out.println("query ......");} }

創(chuàng)建一個(gè)切面

@Aspect @Component public class DemoAspect {// 配置切點(diǎn)@Pointcut("execution(* com.aspectj.dao.*.*(..))")public void point(){}// 切點(diǎn)通知@Before("point()")public void beforeAdd(){System.out.println("before-------------");} }

創(chuàng)建啟動(dòng)類(lèi)

public class TestAspect {public static void main(String[] args) {// 刷新容器AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(DemoAspectJConfig.class)// 獲取 bean 對(duì)象DemoDao dao = configApplicationContext.getBean(DemoDao.class);// 代理對(duì)象執(zhí)行dao.query();} }

啟動(dòng) main() 方法,可以看到輸出的內(nèi)容,AOP 配置方法執(zhí)行


Spring AOP 執(zhí)行流程


源碼解讀

代碼入口






前置處理

判斷是否是切面








構(gòu)建 bean 對(duì)象 advisors 流程
① 遍歷所有的類(lèi)
② 判斷是否切面,只有切面才會(huì)進(jìn)入后面邏輯
③ 獲取每個(gè) Aspect 的切面列表
④ 保存 Aspect 的切面列表到緩存 advisorsCache<beanName,advisors> 中


獲取切面列表







到這一步,前置處理已經(jīng)完成 !

后置處理

獲取切面






創(chuàng)建代理對(duì)象



對(duì)象增強(qiáng)處理流程
① 獲取當(dāng)前 bean 對(duì)象 advisors 列表,判斷是否為空
② 不為空就創(chuàng)建代理對(duì)象

















切面執(zhí)行



實(shí)例化 ReflectiveMethodInvocation 對(duì)象,調(diào)用 proceed() 方法


第一次遞歸

數(shù)組的第一個(gè)對(duì)象是 ExposeInvocationInterceptor,執(zhí)行 invoke(),注意入?yún)⑹?ReflectiveMethodInvocation


第二次遞歸

數(shù)組的第二個(gè)對(duì)象是 MethodBeforeAdviceInterceptor,執(zhí)行 invoke()




第三次遞歸

如果 advisor 有后置處理,就執(zhí)行第三次遞歸


跳出遞歸


總結(jié)

  • AOP 實(shí)現(xiàn)原理
    • 將所有的切面都保存在緩存中
    • 取出緩存中的切面列表,和 bean 對(duì)象的所有方法匹配,拿到屬于 bean 對(duì)象的切面列表
    • 創(chuàng)建 AOP 代理對(duì)象
    • 通過(guò) “責(zé)任鏈 + 遞歸”,去執(zhí)行切面邏輯

總結(jié)

以上是生活随笔為你收集整理的Spring AOP 超详细源码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。