沒被洪水灌溉過,你怎麼能證明這個城市的下水道架構師合理的呢?
【小家Spring】探索Spring AOP中aopalliance的Joinpoint、MethodInvocation、Interceptor、MethodInterceptor…
【小家Spring】Spring AOP原理使用的基礎類打點(AopInfrastructureBean、Advised、AjType、AspectJExpressionPointcut)
【小家Spring】詳解Spring AOP的底層代理JdkDynamicAopProxy和ObjenesisCglibAopProxy的源碼分析(介紹CGLIB使用中的坑)
Spring AOP是整個Spring架構中最重要的内容之一。為了更好的深入檢視它的原理,這篇文章主要是把它在關鍵位置使用到的一些常用類進行打點、解釋一波,有助于我們去看源代碼的時候變得更加的輕松、流暢
Spring AOP相關類、元件内容龐大。此處隻會介紹一些最為常用的概念進行分析~~~

<code>AopInfrastructureBean</code>是一個标記接口。若Bean實作了此接口,表明它是一個Spring AOP的基礎類,那麼這個類是不會被AOP給代理的,即使它能被切面切進去~~~
用于建立代理的配置的父類,以確定所有代理建立者具有一緻的屬性。 它有五個屬性,解釋如下:
簡單的說它就是提供為代理建立器提供了一些公共方法實作:
這個類應該很熟了,我們之前介紹過的三大建立代理對象的工廠<code>ProxyFactoryBean、ProxyFactory、AspectJProxyFactory</code>都是繼承自此類的
參考:【小家Spring】面向切面程式設計Spring AOP建立代理的方式:ProxyFactoryBean、ProxyFactory、AspectJProxyFactory(JDK Proxy和CGLIB)
<code>ProxyCreatorSupport</code>用于設定和儲存下面三大資訊:
設定被代理對象target
設定代理接口
設定通知advice
ProxyCreatorSupport繼承AdvisedSupport,主要提供了createAopProxy方法用來得到用來生成代理對象的AopProxy對象:
Objenesis是專門用于執行個體化一些特殊java對象的一個工具,如私有構造方法。我們知道帶參數的構造等不能通過<code>class.newInstance()</code>執行個體化的,通過它可以輕松完成 基于Objenesis的CglibAopProxy擴充,用于建立代理執行個體,沒有調用類的構造器(厲害了)
Advice: 通知攔截器
Advisor: 通知 + 切入點的擴充卡
Advised: 包含所有的Advised 和 Advice
該接口用于儲存一個代理的相關配置。比如儲存了這個代理相關的攔截器、通知、增強器等等。
所有的代理對象都實作了該接口(我們就能夠通過一個代理對象擷取這個代理對象怎麼被代理出來的相關資訊)
不管是JDKproxy,還是cglib proxy,代理出來的對象都實作了org.springframework.aop.framework.Advised接口;
下面看看基礎實作AdvisedSupport
它最重要的一個方法是:提供<code>getInterceptorsAndDynamicInterceptionAdvice</code>方法用來擷取對應代理方法對應有效的攔截器鍊
<code>AdvisedSupport</code>本身不會提供建立代理的任何方法,專注于生成攔截器鍊。委托給<code>ProxyCreatorSupport</code>去建立代理對象
spring aop架構對<code>BeforeAdvice、AfterAdvice、ThrowsAdvice</code>三種通知類型的支援實際上是借助擴充卡模式來實作的,這樣的好處是使得架構允許使用者向架構中加入自己想要支援的任何一種通知類型
的<code>AdvisorAdapter</code>是一個擴充卡接口,它定義了自己支援的Advice類型,并且能把一個Advisor适配成<code>MethodInterceptor</code>(這也是AOP聯盟定義的借口),以下是它的定義
一般我們自己并不需要自己去提供此接口的實作(除非你還行适配被的Advice進來),因為Spring為我們提供了對應的實作:
實作也非常的簡單,如下:
參考:<code>AdvisorAdapterRegistry</code>和<code>DefaultAdvisorAdapterRegistry</code>,<code>GlobalAdvisorAdapterRegistry</code>用于管理管理AdvisorAdapter的
如果我們想把自己定義的AdvisorAdapter注冊到spring aop架構中,怎麼辦?
把我們自己寫好得AdvisorAdapter放進Spring IoC容器中
配置一個<code>AdvisorAdapterRegistrationManager</code>,它是一個<code>BeanPostProcessor</code>,它會檢測所有的Bean。若是AdvisorAdapter類型,就:<code>this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);</code>
該接口代表一個目标對象,在aop調用目标對象的時候,使用該接口傳回真實的對象。
比如它有其中兩個實作<code>SingletonTargetSource</code>和<code>PrototypeTargetSource</code>代表着每次調用傳回同一個執行個體,和每次調用傳回一個新的執行個體
<code>所有的</code>Aop代理對象或者代理工廠(proxy factory)都要實作的接口,該接口用于暴露出被代理目标對象類型;
表示一個切面的中繼資料類。
Spring AOP支援AspectJ的<code>singleton、perthis、pertarget、pertypewithin</code>執行個體化模型(目前不支援percflow、percflowbelow) 參見枚舉類<code>PerClauseKind</code>
singleton:即切面隻會有一個執行個體;
perthis:每個切入點表達式比對的連接配接點對應的<code>AOP對象(代理對象)</code>都會建立一個新切面執行個體;
pertarget:每個切入點表達式比對的連接配接點對應的目标對象都會建立一個新的切面執行個體
<code>pertypewithin</code>:
預設是singleton執行個體化模型,Schema風格隻支援singleton執行個體化模型,而@AspectJ風格支援這三種執行個體化模型
<code>singleton</code>:使用@Aspect()指定,即預設就是單例執行個體化模式,在此就不示範示例了
<code>perthis</code>:每個切入點表達式比對的連接配接點對應的AOP代理對象都會建立一個新的切面執行個體,使用<code>@Aspect("perthis(切入點表達式)")</code>指定切入點表達式;
<code>pertarget</code>:每個切入點表達式比對的連接配接點對應的目标對象都會建立一個新的切面執行個體,使用<code>@Aspect("pertarget(切入點表達式)")</code>指定切入點表達式; 此處要求HelloService不能是接口
另外需要注意一點:若在Spring内要使用perthis和pertarget,請把切面的Scope定義為:<code>prototype</code>
專門為切面建立執行個體的工廠(因為切面也不一定是單例的,也支援各種多例形式。上面已有說明)
它的實作類如下:
<code>SimpleAspectInstanceFactory</code>:根據切面的aspectClass,調用空構造函數反射.newInstance()建立一個執行個體(備注:構造函數private的也沒有關系)
<code>SingletonAspectInstanceFactory</code>:這個就更簡單了,因為已經持有aspectInstance得引用了,直接return即可
<code>AspectInstanceFactory</code>的子接口。提供了擷取<code>AspectMetadata</code>的方法
<code>SimpleMetadataAwareAspectInstanceFactory</code>和<code>SingletonMetadataAwareAspectInstanceFactory</code>已經直接關聯到<code>AspectMetadata</code>,是以直接return即可。
<code>LazySingletonAspectInstanceFactoryDecorator</code>也隻是個簡單的裝飾而已。
這個就和Bean工廠有關了。比較重要
PrototypeAspectInstanceFactory:多例專用的工廠 若是多例的,推薦使用
下面介紹下<code>aspectj</code>這個jar包下幾個重要的類
AjTypeImpl是<code>AjType</code>的唯一實作類,因為方法實在是太多了,是以下面我隻展示一些覺得比較有意思的方法實作:
工欲善其事必先利其器,任何負責的架構、業務也好。都是由一部分一部分的元件組合而成的。本文主旨就是單獨把元件拆出來講解,逐個擊破~~