Spring AOP(一) AOP的基本概念

Spring框架自誕生之日就拯救我等程序員于水火之中,它有兩大法寶,一個是IoC控制反轉,另一個便是AOP面向切面編程拒迅。今日我們就來破一下它的AOP法寶,以便以后也能自由使出一手AOP大法她倘。
AOP全名Aspect-oriented programming面向切面編程大法璧微,它有很多兄弟,分別是經(jīng)常見的面向對象編程硬梁,樸素的面向過程編程和神秘的函數(shù)式編程等往毡。所謂AOP的具體解釋,以及和OOP的區(qū)別不清楚的同學可以自行去了解靶溜。
AOP實現(xiàn)的關鍵在于AOP框架自動創(chuàng)建的AOP代理开瞭,AOP代理主要分為靜態(tài)代理和動態(tài)代理。本文就主要講解AOP的基本術語罩息,然后用一個例子讓大家徹底搞懂這些名詞嗤详,最后介紹一下AOP的兩種代理方式:
**· **以AspectJ為代表的靜態(tài)代理。
**· **以Spring AOP為代表的動態(tài)代理瓷炮。

基本術語

(1)切面(Aspect)

切面是一個橫切關注點的模塊化葱色,一個切面能夠包含同一個類型的不同增強方法,比如說事務處理和日志處理可以理解為兩個切面娘香。切面由切入點和通知組成苍狰,它既包含了橫切邏輯的定義办龄,也包括了切入點的定義。 Spring AOP就是負責實施切面的框架淋昭,它將切面所定義的橫切邏輯織入到切面所指定的連接點中俐填。

@Component
@Aspect
public class LogAspect {
}

可以簡單地認為, 使用 @Aspect 注解的類就是切面

(2) 目標對象(Target)

目標對象指將要被增強的對象,即包含主業(yè)務邏輯的類對象翔忽∮⑷冢或者說是被一個或者多個切面所通知的對象。

(3) 連接點(JoinPoint)

程序執(zhí)行過程中明確的點歇式,如方法的調(diào)用或特定的異常被拋出驶悟。連接點由兩個信息確定:
**· **方法(表示程序執(zhí)行點,即在哪個目標方法)
**· **相對點(表示方位材失,即目標方法的什么位置痕鳍,比如調(diào)用前,后等)
簡單來說龙巨,連接點就是被攔截到的程序執(zhí)行點额获,因為Spring只支持方法類型的連接點,所以在Spring中連接點就是被攔截到的方法恭应。

@Before("pointcut()")
public void log(JoinPoint joinPoint) { //這個JoinPoint參數(shù)就是連接點
}

(4) 切入點(PointCut)

切入點是對連接點進行攔截的條件定義。切入點表達式如何和連接點匹配是AOP的核心耘眨,Spring缺省使用AspectJ切入點語法昼榛。 一般認為,所有的方法都可以認為是連接點剔难,但是我們并不希望在所有的方法上都添加通知胆屿,而切入點的作用就是提供一組規(guī)則(使用 AspectJ pointcut expression language 來描述) 來匹配連接點,給滿足規(guī)則的連接點添加通知偶宫。

@Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))")
public void pointcut() {
}

上邊切入點的匹配規(guī)則是com.remcarpediem.test.aop.service包下的所有類的所有函數(shù)非迹。

(5) 通知(Advice)

通知是指攔截到連接點之后要執(zhí)行的代碼,包括了“around”纯趋、“before”和“after”等不同類型的通知憎兽。Spring AOP框架以攔截器來實現(xiàn)通知模型,并維護一個以連接點為中心的攔截器鏈吵冒。

// @Before說明這是一個前置通知纯命,log函數(shù)中是要前置執(zhí)行的代碼,JoinPoint是連接點痹栖,
@Before("pointcut()")
public void log(JoinPoint joinPoint) { 
}

(6) 織入(Weaving)

織入是將切面和業(yè)務邏輯對象連接起來, 并創(chuàng)建通知代理的過程亿汞。織入可以在編譯時揪阿,類加載時和運行時完成疗我。在編譯時進行織入就是靜態(tài)代理咆畏,而在運行時進行織入則是動態(tài)代理。

(7) 增強器(Adviser)

Advisor是切面的另外一種實現(xiàn)吴裤,能夠將通知以更為復雜的方式織入到目標對象中旧找,是將通知包裝為更復雜切面的裝配器。Advisor由切入點和Advice組成嚼摩。 Advisor這個概念來自于Spring對AOP的支撐钦讳,在AspectJ中是沒有等價的概念的。Advisor就像是一個小的自包含的切面枕面,這個切面只有一個通知愿卒。切面自身通過一個Bean表示,并且必須實現(xiàn)一個默認接口潮秘。

// AbstractPointcutAdvisor是默認接口public class LogAdvisor extends AbstractPointcutAdvisor {
    private Advice advice; // Advice
    private Pointcut pointcut; // 切入點
    @PostConstruct
    public void init() {
        // AnnotationMatchingPointcut是依據(jù)修飾類和方法的注解進行攔截的切入點琼开。
        this.pointcut = new AnnotationMatchingPointcut((Class) null, Log.class);
        // 通知
        this.advice = new LogMethodInterceptor();
}
}

深入理解

看完了上面的理論部分知識, 我相信還是會有不少朋友感覺AOP 的概念還是很模糊, 對 AOP 的術語理解的還不是很透徹。現(xiàn)在我們就找一個具體的案例來說明一下枕荞。 簡單來講柜候,整個 aspect 可以描述為: 滿足 pointcut 規(guī)則的 joinpoint 會被添加相應的 advice 操作。我們來看下邊這個例子躏精。

@Component
@Aspect // 切面public class LogAspect {
    privatefinal staticLogger LOGGER = LoggerFactory.getLogger(LogAspect.class.getName());
     // 切入點渣刷,表達式是指com.remcarpediem.test.aop.service
     // 包下的所有類的所有方法
    @Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))")
    public void aspect() {}
    // 通知,在符合aspect切入點的方法前插入如下代碼矗烛,并且將連接點作為參數(shù)傳遞
    @Before("aspect()")
    public void log(JoinPoint joinPoint) { //連接點作為參數(shù)傳入
        if (LOGGER.isInfoEnabled()) {
            // 獲得類名辅柴,方法名,參數(shù)和參數(shù)名稱瞭吃。
Signature signature = joinPoint.getSignature();
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
            Object[]arguments = joinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            String[]argumentNames = methodSignature.getParameterNames();
StringBuilder sb = new StringBuilder(className + "." +methodName + "(");
            for (int i = 0; i< arguments.length; i++) {
Object argument = arguments[i];
                sb.append(argumentNames[i] + "->");
                sb.append(argument != null ? argument.toString() : "null ");
            }
            sb.append(")");
            LOGGER.info(sb.toString());
        }
}
}

上邊這段代碼是一個簡單的日志相關的切面碌嘀,依次定義了切入點和通知,而連接點作為log的參數(shù)傳入進來歪架,進行一定的操作股冗,比如說獲取連接點函數(shù)的名稱,參數(shù)等和蚪。

靜態(tài)代理模式

所謂靜態(tài)代理就是AOP框架會在編譯階段生成AOP代理類止状,因此也稱為編譯時增強。ApsectJ是靜態(tài)代理的實現(xiàn)之一攒霹,也是最為流行的导俘。靜態(tài)代理由于在編譯時就生成了代理類,效率相比動態(tài)代理要高一些剔蹋。AspectJ可以單獨使用旅薄,也可以和Spring結合使用。

動態(tài)代理模式

與靜態(tài)代理不同,動態(tài)代理就是說AOP框架不會去修改編譯時生成的字節(jié)碼少梁,而是在運行時在內(nèi)存中生成一個AOP代理對象洛口,這個AOP對象包含了目標對象的全部方法,并且在特定的切點做了增強處理凯沪,并回調(diào)原對象的方法第焰。
Spring AOP中的動態(tài)代理主要有兩種方式:JDK動態(tài)代理和CGLIB動態(tài)代理。
JDK代理通過反射來處理被代理的類妨马,并且要求被代理類必須實現(xiàn)一個接口挺举。核心類是 InvocationHandler接口 和 Proxy類。 而當目標類沒有實現(xiàn)接口時烘跺,Spring AOP框架會使用CGLIB來動態(tài)代理目標類湘纵。 CGLIB(Code Generation Library),是一個代碼生成的類庫滤淳,可以在運行時動態(tài)的生成某個類的子類梧喷。CGLIB是通過繼承的方式做的動態(tài)代理,因此如果某個類被標記為final脖咐,那么它是無法使用CGLIB做動態(tài)代理的铺敌。核心類是 MethodInterceptor 接口和Enhancer 類


兩種動態(tài)代理的區(qū)別【加群】:857565362

后記

AOP的基礎知識都比較枯燥,本人也不擅長概念性的文章屁擅,不過下一篇文章就是AOP源碼分析了偿凭,希望大家可以繼續(xù)關注。
我這兒整理了比較全面的JAVA相關的面試資料派歌,
需要領取面試資料的同學弯囊,請加群:473984645



獲取更多學習資料,可以加群:473984645或掃描下方二維碼


?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末硝皂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子作谭,更是在濱河造成了極大的恐慌稽物,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件折欠,死亡現(xiàn)場離奇詭異贝或,居然都是意外死亡,警方通過查閱死者的電腦和手機锐秦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門咪奖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酱床,你說我怎么就攤上這事羊赵。” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵昧捷,是天一觀的道長闲昭。 經(jīng)常有香客問我,道長靡挥,這世上最難降的妖魔是什么序矩? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮跋破,結果婚禮上簸淀,老公的妹妹穿的比我還像新娘。我一直安慰自己毒返,他們只是感情好租幕,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著饿悬,像睡著了一般令蛉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狡恬,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天珠叔,我揣著相機與錄音,去河邊找鬼弟劲。 笑死祷安,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的兔乞。 我是一名探鬼主播汇鞭,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼庸追!你這毒婦竟也來了霍骄?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤淡溯,失蹤者是張志新(化名)和其女友劉穎读整,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咱娶,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡米间,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了膘侮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈糊。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖琼了,靈堂內(nèi)的尸體忽然破棺而出逻锐,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布谦去,位于F島的核電站慷丽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鳄哭。R本人自食惡果不足惜要糊,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妆丘。 院中可真熱鬧锄俄,春花似錦、人聲如沸勺拣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽药有。三九已至毅戈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愤惰,已是汗流浹背苇经。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宦言,地道東北人扇单。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像奠旺,于是被迫代替她去往敵國和親蜘澜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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