當前位置:
首頁 > 最新 > 淺析Spring AOP

淺析Spring AOP

本文大概:1200字閱讀需要:15分鐘

Aop(Aspect-OrientedProgramming)面向切面編程是對OOP的補充,專註於系統中不同模塊統一的處理邏輯,比如事務管理,日誌管理,緩存等系統級服務。

眾所周知,SpringAop基於代理實現的,比如JDK動態代理和CGLIB代理。

既然如此,在這之前先初探JDK動態代理。

那麼如何使用JDK動態代理呢?

1):創建實現了InvocationHandler介面的類,實現invoke方法,該方法將在與之關聯的代理類方法調用的時候執行

2):通過Proxy.newProxyInstance()方法返回代理對象

target為需要代理的目標對象,一般實現了某個介面,本例中Pojo介面只有兩個簡單方法

SimplePojo實現了Pojo介面,當調用bar(),foo()方法時,最終會調用invoke方法,實現攔截的邏輯。

為什麼最終會調用invoke方法呢?

主要原因還在於Proxy.newProxyInstance()返回了一個代理類,該類以$Proxy開頭,並實現了目標對象所實現的介面,並把實現了InvocationHandler的類作為代理類的構造參數;

如上例子,會產生一個name為$Proxy0的類,同時實現了Pojo介面。

因此,從生成的class可以看出,當調用foo(),bar()方法時,最終會調用invoke方法,可以在目標方法的調用前後實現其他的業務邏輯。

分析完JDK動態代理,下面正式進入springAop的世界,對於如何使用AOP,本文不做過多的分析,並以註解的形式進行淺析。

這一切又是怎麼發生了呢?

整個過程大致分為四步:

1.註冊Aop處理器

Spring容器在載入配置文件解析標籤時,會在spring-aop.jar包下的META-INF文件下找到spring.handlers的properties文件

該handler會註冊針對標籤的解析器

其主要作用即向容器注入處理@Aspect註解的bean

AnnotationAwareAspectJAutoProxyCreator的類層次圖如下圖所示:

可以看出該類實現了BeanPostProcessor介面,Spring文檔對該介面的解釋即允許對bean進行修改,比如返回代理。

而Spring容器在初始化bean的時候會調用beanpost processor(bean的創建過程本文不做分析),本文最後附上了BeanPostProcessor的一個應用。

2.查找容器內所有的Advisors

該邏輯在AnnotationAwareAspectJAutoProxyCreator.findCadidateAdvisors()方法,其主要邏輯即是尋找容器中標有@Aspect註解的類以及配置文件中的

@Aspect的處理邏輯大概概括為:提取標有@Aspect註解類的方法(排除了標有@PonitCut註解的方法),對標記有@Aroud,@Before,@After,@AfterReturing,@AfterThrowing的方法封裝為Advisor.並且返回的是有序的集合,順序分別是@Around,@Before,@After,@AfterReturning,@AfterThrowing。此時即提取了所有的Advisor.

3.查找符合條件的bean

findAdvisorsThatCanApply的主要邏輯是尋找匹配當前bean的Advisor.從編碼的角度來看,即當前bean匹配Advisor的切入點表達式;比如:execution(*com.dr.demo..*.*(..)),即com.dr.demo包以及其子包下的類的任何方法都應進行增強。

4.創建代理對象

前面第一點提到AnnotationAwareAspectJAutoProxyCreator實現了BeanProcessor介面,此處即對容器里符合條件的bean創建代理。

Spring提供2種方式實現代理:CGLIB代理以及JDK代理,比如設置了proxy-target-class,則會使用Cglib代理,本文以JDK動態代理為例,分析創建代理對象的過程。

本文開篇即分析了JDK動態代理原理,以及使用方式,看看spring又是如何實現呢?

JdkDynamicAopProxy同樣實現了InvocationHandler,其getProxy方法返回代理對象,代理的介面即為第3步找到的Advisor.

因此,當從spring容器里獲取對象時,其實質是返回的代理對象;當執行方法時,均會執行invoke方法,以下代碼片段是invoke方法的一部分,封裝攔截器鏈(不止一個增加),隨後遍歷攔截器鏈,執行攔截器方法,直到攔截器鏈執行完畢,在執行目標方法。

小結:以上只是對springaop粗略的分析,springaop的實現極為複雜,比如切入點表達的提取,以及joinPoint與PointCut的匹配等內容。

參考文獻:

https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-introduction-defn


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 點融黑幫 的精彩文章:

快一點,再快一點
今天我們來聊一聊運動這件事
淺談 golang channel
從InnoDB了解MVCC
需求分析的套與路

TAG:點融黑幫 |