Spring AOP,AspectJ, CGLIB 有點暈

AOP(Aspect Orient Programming)下梢,作為面向?qū)ο缶幊痰囊环N補(bǔ)充,廣泛應(yīng)用于處理一些具有橫切性質(zhì)的系統(tǒng)級服務(wù)塞蹭,如事務(wù)管理孽江、安全檢查、緩存番电、對象池管理等岗屏。AOP 實現(xiàn)的關(guān)鍵就在于 AOP 框架自動創(chuàng)建的 AOP 代理,AOP 代理則可分為靜態(tài)代理和動態(tài)代理兩大類漱办,其中靜態(tài)代理是指使用 AOP 框架提供的命令進(jìn)行編譯这刷,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時增強(qiáng)娩井;而動態(tài)代理則在運行時借助于 JDK 動態(tài)代理崭歧、CGLIB 等在內(nèi)存中“臨時”生成 AOP 動態(tài)代理類,因此也被稱為運行時增強(qiáng)撞牢。

先說說AspectJ

在今天之前率碾,我還以為AspectJ 是Spring的一部分,因為我們談到Spring AOP一般都會提到AspectJ屋彪。原來AspectJ是一套獨立的面向切面編程的解決方案所宰。下面我們拋開Spring,單純的看看AspectJ畜挥。

  1. AspectJ 安裝
    AspectJ 下載地址(http://www.eclipse.org/aspectj/downloads.php)仔粥。
    下載AspectJ jar包,然后雙擊安裝蟹但。安裝好的目錄結(jié)構(gòu)為:
    bin:存放了 aj躯泰、aj5、ajc华糖、ajdoc麦向、ajbrowser 等命令,其中 ajc 命令最常用客叉,它的作用類似于 javac
    doc:存放了 AspectJ 的使用說明诵竭、參考手冊话告、API 文檔等文檔
    lib:該路徑下的 4 個 JAR 文件是 AspectJ 的核心類庫
  2. AspectJ HelloWorld 實現(xiàn)
業(yè)務(wù)組件  SayHelloService
package com.ywsc.fenfenzhong.aspectj.learn;
public class SayHelloService {
    public void say(){
        System.out.print("Hello  AspectJ");
    }
} 
需要來了,在需要在調(diào)用say()方法之后卵慰,需要記錄日志沙郭。那就是通過AspectJ的后置增強(qiáng)吧。 
LogAspect 日志記錄組件裳朋,實現(xiàn)對com.ywsc.fenfenzhong.aspectj.learn.SayHelloService 后置增強(qiáng)
package com.ywsc.fenfenzhong.aspectj.learn;
public aspect LogAspect{
    pointcut logPointcut():execution(void SayHelloService.say());
    after():logPointcut(){
         System.out.println("記錄日志 ..."); 
    }
}
  1. 編譯SayHelloService
執(zhí)行命令   ajc -d . SayHelloService.java LogAspect.java
生成 SayHelloService.class
執(zhí)行命令    java SayHelloService
輸出  Hello AspectJ  記錄日志

ajc.exe 可以理解為 javac.exe 命令病线,都用于編譯 Java 程序,區(qū)別是 ajc.exe 命令可識別 AspectJ 的語法鲤嫡;我們可以將 ajc.exe 當(dāng)成一個增強(qiáng)版的 javac.exe 命令.執(zhí)行ajc命令后的 SayHelloService.class 文件不是由原來的 SayHelloService.java 文件編譯得到的氧苍,該 SayHelloService.class 里新增了打印日志的內(nèi)容——這表明 AspectJ 在編譯時“自動”編譯得到了一個新類,這個新類增強(qiáng)了原有的 SayHelloService.java 類的功能泛范,因此 AspectJ 通常被稱為編譯時增強(qiáng)的 AOP 框架。
與 AspectJ 相對的還有另外一種 AOP 框架紊撕,它不需要在編譯時對目標(biāo)類進(jìn)行增強(qiáng)罢荡,而是運行時生成目標(biāo)類的代理類,該代理類要么與目標(biāo)類實現(xiàn)相同的接口对扶,要么是目標(biāo)類的子類——總之区赵,代理類的實例可作為目標(biāo)類的實例來使用。一般來說浪南,編譯時增強(qiáng)的 AOP 框架在性能上更有優(yōu)勢——因為運行時動態(tài)增強(qiáng)的 AOP 框架需要每次運行時都進(jìn)行動態(tài)增強(qiáng)笼才。

再談 Spring AOP

Spring AOP也是對目標(biāo)類增強(qiáng),生成代理類络凿。但是與AspectJ的最大區(qū)別在于---Spring AOP的運行時增強(qiáng)骡送,而AspectJ是編譯時增強(qiáng)。
曾經(jīng)以為AspectJ是Spring AOP一部分絮记,是因為Spring AOP使用了AspectJ的Annotation摔踱。使用了Aspect來定義切面,使用Pointcut來定義切入點,使用Advice來定義增強(qiáng)處理怨愤。雖然使用了Aspect的Annotation派敷,但是并沒有使用它的編譯器和織入器。其實現(xiàn)原理是JDK 動態(tài)代理撰洗,在運行時生成代理類篮愉。
為了啟用 Spring 對 @AspectJ 方面配置的支持,并保證 Spring 容器中的目標(biāo) Bean 被一個或多個方面自動增強(qiáng)差导,必須在 Spring 配置文件中添加如下配置

   <aop:aspectj-autoproxy/>

當(dāng)啟動了 @AspectJ 支持后试躏,在 Spring 容器中配置一個帶 @Aspect 注釋的 Bean,Spring 將會自動識別該 Bean设褐,并將該 Bean 作為方面 Bean 處理冗酿。方面Bean與普通 Bean 沒有任何區(qū)別埠对,一樣使用 <bean.../> 元素進(jìn)行配置,一樣支持使用依賴注入來配置屬性值裁替。
使用Spring AOP的改寫 Hello World的例子项玛。

業(yè)務(wù)組件  SayHelloService
package com.ywsc.fenfenzhong.aspectj.learn;
import org.springframework.stereotype.Component;
@Component
public class SayHelloService {
    public void say(){
        System.out.print("Hello  AspectJ");
    }
} 

做后置增強(qiáng)的日志處理。

package com.ywsc.fenfenzhong.aspectj.learn;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
     @After("execution(* com.ywsc.fenfenzhong.aspectj.learn.SayHelloService.*(..))")
     public void log(){
         System.out.println("記錄日志 ...");
     }
}
package com.ywsc.fenfenzhong.mongodb;
import com.ywsc.fenfenzhong.aspectj.learn.SayHelloService;
public class TestCase {
    public static void main(String[] args) {
        SayHelloService sayHelloService = ApplicationUtil.getContext().getBean(SayHelloService.class);
        sayHelloService.say();
    }
}
輸出結(jié)果
Hello  AspectJ
記錄日志...```
####Hello World后的總結(jié)
AOP 代理 = 原來的業(yè)務(wù)類+增強(qiáng)處理弱判。
這個生成AOP 代理由 Spring 的 IoC 容器負(fù)責(zé)生成襟沮。也由 IoC 容器負(fù)責(zé)管理。因此昌腰,AOP 代理可以直接使用容器中的其他 Bean 實例作為目標(biāo)开伏,這種關(guān)系可由 IoC 容器的依賴注入提供≡馍蹋回顧Hello World的例子固灵,其中程序員參與的只有 3 個部分:
. 定義普通業(yè)務(wù)組件。
. 定義切入點劫流,一個切入點可能橫切多個業(yè)務(wù)組件巫玻。
. 定義增強(qiáng)處理,增強(qiáng)處理就是在 AOP 框架為普通業(yè)務(wù)組件織入的處理動作祠汇。

###最后說說CGLIB
CGLIB(Code Generation Library)它是一個代碼生成類庫仍秤。它可以在運行時候動態(tài)是生成某個類的子類。代理模式為要訪問的目標(biāo)對象提供了一種途徑可很,當(dāng)訪問對象時诗力,它引入了一個間接的層。JDK自從1.3版本開始我抠,就引入了動態(tài)代理苇本,并且經(jīng)常被用來動態(tài)地創(chuàng)建代理。JDK的動態(tài)代理用起來非常簡單菜拓,唯一限制便是使用動態(tài)代理的對象必須實現(xiàn)一個或多個接口圈澈。而CGLIB缺不必有此限制。要想Spring AOP 通過CGLIB生成代理尘惧,只需要在Spring 的配置文件引入
```xml
<aop:aspectj-autoproxy proxy-target-class="true"/>

CGLIB包的底層是通過使用一個小而快的字節(jié)碼處理框架ASM(Java字節(jié)碼操控框架)康栈,來轉(zhuǎn)換字節(jié)碼并生成新的類。由于沒有了解過class 文件和字節(jié)碼喷橙,因而也就寫不下去了啥么。
也許學(xué)習(xí)下來最大的收獲便是 弄清楚了 AspectJ 和 Spring AOP 在實現(xiàn)上幾乎無關(guān)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贰逾,一起剝皮案震驚了整個濱河市悬荣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疙剑,老刑警劉巖氯迂,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件践叠,死亡現(xiàn)場離奇詭異,居然都是意外死亡嚼蚀,警方通過查閱死者的電腦和手機(jī)禁灼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轿曙,“玉大人弄捕,你說我怎么就攤上這事〉嫉郏” “怎么了守谓?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長您单。 經(jīng)常有香客問我斋荞,道長,這世上最難降的妖魔是什么虐秦? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任平酿,我火速辦了婚禮,結(jié)果婚禮上羡疗,老公的妹妹穿的比我還像新娘。我一直安慰自己别洪,他們只是感情好叨恨,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挖垛,像睡著了一般痒钝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痢毒,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天送矩,我揣著相機(jī)與錄音,去河邊找鬼哪替。 笑死栋荸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凭舶。 我是一名探鬼主播晌块,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼帅霜!你這毒婦竟也來了匆背?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤身冀,失蹤者是張志新(化名)和其女友劉穎钝尸,沒想到半個月后括享,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡珍促,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年萌业,在試婚紗的時候發(fā)現(xiàn)自己被綠了半沽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盖喷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侥蒙,我是刑警寧澤崔兴,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站藏否,受9級特大地震影響瓶殃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜副签,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一遥椿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淆储,春花似錦冠场、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至点额,卻和暖如春舔株,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背还棱。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工载慈, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人珍手。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓办铡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親琳要。 傳聞我的和親對象是個殘疾皇子料扰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)焙蹭,斷路器晒杈,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • AOP實現(xiàn)可分為兩類(按AOP框架修改源代碼的時機(jī)): 靜態(tài)AOP實現(xiàn):AOP框架在編譯階段對程序進(jìn)行修改拯钻,即實現(xiàn)...
    數(shù)獨題閱讀 2,317評論 0 22
  • 什么是Spring Spring是一個開源的Java EE開發(fā)框架帖努。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,461評論 1 133
  • Spring簡介 spring框架由Rod Johnson開發(fā),2004年發(fā)布了Spring框架的第一版粪般。Spri...
    qiuqiu_hz閱讀 1,077評論 0 15
  • 如下是整篇文章的結(jié)構(gòu)拼余,所需閱讀時間大約20min Spring簡介 Spring框架由Rod Johnson開發(fā),...
    李序鍇閱讀 893評論 0 15