《Spring實(shí)戰(zhàn)》筆記(三):AOP

1 AOP術(shù)語(yǔ)

AOP的術(shù)語(yǔ)主要有如下幾個(gè):

  • 通知(Advice)
  • 連接點(diǎn)(Join point)
  • 切點(diǎn)(Pointcut)
  • 切面(Aspect)
  • 引入(Introduction)
  • 織入(Weaving)
  1. 通知
    在AOP術(shù)語(yǔ)中屹篓,切面的工作被稱為通知。通知定義了切面是什么以及何時(shí)使用。除了描述切面要完成的工作,通知還解決了何時(shí)執(zhí)行這個(gè)工作的問(wèn)題。
    Spring切面可以應(yīng)用5種類型的通知:
  • 前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;
  • 后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時(shí)不會(huì)關(guān)心方法的輸出是什么背伴;
  • 返回通知(After-returning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;
  • 異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知峰髓;
  • 環(huán)繞通知(Around):通知包裹了被通知的方法傻寂,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為。
  1. 連接點(diǎn)
    連接點(diǎn)是在應(yīng)用執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn)携兵。這個(gè)點(diǎn)可以是調(diào)用方法時(shí)疾掰、拋出異常時(shí)、甚至修改一個(gè)字段時(shí)眉孩。切面代碼可以利用這些點(diǎn)插入到應(yīng)用的正常流程之中个绍,并添加新的行為。
  2. 切點(diǎn)
    如果說(shuō)通知定義了切面的“什么”和“何時(shí)”的話浪汪,那么切點(diǎn)就定義了“何處”巴柿。切點(diǎn)的定義會(huì)匹配通知所要織入的一個(gè)或多個(gè)連接點(diǎn)。
  3. 切面
    切面是通知和切點(diǎn)的結(jié)合死遭。通知和切點(diǎn)共同定義了切面的全部?jī)?nèi)容——它是什么广恢,在何時(shí)和何處完成其功能。
  4. 引入
    引入允許我們向現(xiàn)有的類添加新方法或?qū)傩浴?/li>
  5. 織入
    織入是把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過(guò)程呀潭。切面在指定的連接點(diǎn)被織入到目標(biāo)對(duì)象中钉迷。在目標(biāo)對(duì)象的生命周期里有多個(gè)點(diǎn)可以進(jìn)行織入:
  • 編譯期:切面在目標(biāo)類編譯時(shí)被織入。這種方式需要特殊的編譯器钠署。AspectJ的織入編譯器就是以這種方式織入切面的糠聪。
  • 類加載期:切面在目標(biāo)類加載到JVM時(shí)被織入。這種方式需要特殊的類加載器(ClassLoader)谐鼎,它可以在目標(biāo)類被引入應(yīng)用之前增強(qiáng)該目標(biāo)類的字節(jié)碼舰蟆。AspectJ 5的加載時(shí)織入(load-time weaving,LTW)就支持以這種方式織入切面。
  • 運(yùn)行期:切面在應(yīng)用運(yùn)行的某個(gè)時(shí)刻被織入身害。一般情況下味悄,在織入切面時(shí),AOP容器會(huì)為目標(biāo)對(duì)象動(dòng)態(tài)地創(chuàng)建一個(gè)代理對(duì)象塌鸯。Spring AOP就是以這種方式織入切面的侍瑟。

2 Spring AOP 簡(jiǎn)介

Spring提供了4種類型的AOP支持:

  • 基于代理的經(jīng)典Spring AOP;
  • 純POJO切面丙猬;
  • @AspectJ注解驅(qū)動(dòng)的切面涨颜;
  • 注入式AspectJ切面(適用于Spring各版本)

Spring AOP的特點(diǎn):

  • 通知是使用標(biāo)準(zhǔn)的Java類寫的
  • 在運(yùn)行時(shí)通知對(duì)象,通過(guò)在代理類中包裹切面淮悼,Spring在運(yùn)行期把切面織入到Spring管理的bean中咐低。
  • 只支持方法級(jí)別的連接點(diǎn)揽思。因?yàn)镾pring基于動(dòng)態(tài)代理袜腥,所以Spring只支持方法連接點(diǎn)。

3 切點(diǎn)的編寫

Spring AOP支持的AspectJ切點(diǎn)指示器.JPG

其中最為常用的是exection()钉汗,其使用方法為:

exection()使用方法.JPG

還可以使用&&, ||, !等操作符羹令,在XML中,則以and, or, not來(lái)表示损痰。
匹配指定包下所有的方法:execution("* com.demo.controller.*(..))
匹配指定包以及其子包下的所有方法:execution("* com.demo..*(..)")
選擇特定的bean(bean()使用bean ID或bean名稱作為參數(shù)來(lái)限制切點(diǎn)只匹配特定的bean):exection(* concert.Performance.perform(..) && bean('woodstock'))

4 定義切面

聲明通知的注解.JPG
@Aspect
public class HelloAspect {

    @Pointcut("execution(* me.ye.springinaction.controller.Controller.hello(..))")
    public void hello() {}

    @Before("hello()")
    public void beforeHello() {
        System.out.println("ready for hello");
    }

    @AfterReturning("hello()")
    public void afterHello() {
        System.out.println("after hello");
    }

    @AfterThrowing("hello()")
    public void errorWhenHello() {
        System.out.println("error when hello");
    }

}

可以使用@Pointcut來(lái)定義切點(diǎn)福侈,也可以直接在通知的注解中直接以切點(diǎn)的表達(dá)式作為參數(shù)。
定義了切面之后卢未,還要注入相應(yīng)的bean肪凛,以及在配置類中啟用自動(dòng)代理@EnableAspectJAutoProxy

@ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class AspectConfig {
    @Bean
    public HelloAspect helloAspect() {
        return new HelloAspect();
    }
}

@Around的用法:

public class HelloAspect {

    @Pointcut("execution(* me.ye.springinaction.controller.Controller.hello(..))")
    public void hello() {}

    @Around("hello()")
    public void helloAspect(ProceedingJoinPoint joinPoint) {

        try {
            System.out.println("ready for hello");
            joinPoint.proceed();
            System.out.println("after hello");
        } catch(Throwable ex) {
            System.out.println("error when hello");
        }
    }
}

當(dāng)要將控制權(quán)交給被通知的方法時(shí),需要調(diào)用ProceedingJoinPoint的proceed()方法辽社。

5 通過(guò)切面引入新功能

切面還可以為bean添加來(lái)自其他接口的方法伟墙,而并不需要真正實(shí)現(xiàn)其他接口。通過(guò)代理滴铅,引入其他接口戳葵,當(dāng)調(diào)用到引入接口的方法時(shí),代理會(huì)將調(diào)用委托給實(shí)現(xiàn)了該接口的其他對(duì)象汉匙。


使用Spring AOP為bean引入新的方法.JPG
@Aspect
public class DeclareParentsAspect {

    @DeclareParents(value = "me.ye.springinaction.service.DemoService", defaultImpl = CommonParentImpl.class)
    private CommonParent commonParent;
}

@DeclareParents注解由三部分組成:

  • value屬性指定了哪種類型的bean要引入該接口拱烁。
  • defaultImpl屬性指定了為引入功能提供實(shí)現(xiàn)的類。
  • @DeclareParents注解所標(biāo)注的屬性指明了要引入的接口噩翠。

使用的時(shí)候可以將bean進(jìn)行類型轉(zhuǎn)換為要引入的接口戏自,再調(diào)用要引入的方法即可。

((CommonParent)service).doSomething();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伤锚,一起剝皮案震驚了整個(gè)濱河市擅笔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖剂娄,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蠢涝,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡阅懦,警方通過(guò)查閱死者的電腦和手機(jī)和二,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)耳胎,“玉大人惯吕,你說(shuō)我怎么就攤上這事∨挛纾” “怎么了废登?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)郁惜。 經(jīng)常有香客問(wèn)我堡距,道長(zhǎng),這世上最難降的妖魔是什么兆蕉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任羽戒,我火速辦了婚禮,結(jié)果婚禮上虎韵,老公的妹妹穿的比我還像新娘易稠。我一直安慰自己,他們只是感情好包蓝,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布驶社。 她就那樣靜靜地躺著,像睡著了一般测萎。 火紅的嫁衣襯著肌膚如雪亡电。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天绳泉,我揣著相機(jī)與錄音逊抡,去河邊找鬼。 笑死零酪,一個(gè)胖子當(dāng)著我的面吹牛冒嫡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播四苇,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孝凌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了月腋?” 一聲冷哼從身側(cè)響起蟀架,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瓣赂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后片拍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體煌集,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年捌省,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苫纤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纲缓,死狀恐怖卷拘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祝高,我是刑警寧澤栗弟,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站工闺,受9級(jí)特大地震影響乍赫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斤寂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一耿焊、第九天 我趴在偏房一處隱蔽的房頂上張望揪惦。 院中可真熱鬧遍搞,春花似錦、人聲如沸器腋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纫塌。三九已至诊县,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間措左,已是汗流浹背依痊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怎披,地道東北人胸嘁。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凉逛,于是被迫代替她去往敵國(guó)和親性宏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

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

  • 本章內(nèi)容: 面向切面編程的基本原理 通過(guò)POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,132評(píng)論 0 9
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理状飞,服務(wù)發(fā)現(xiàn)毫胜,斷路器书斜,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 在生活中荐吉,監(jiān)控用電量是一個(gè)很重要的功能,但并不是大多數(shù)家庭重點(diǎn)關(guān)注的問(wèn)題口渔。軟件系統(tǒng)的一些功能就像家里的電表一樣稍坯,這...
    yjaal閱讀 569評(píng)論 0 3
  • 兩種生成jsbundle方式: curl命令download jsbundle react-native bund...
    生光閱讀 4,818評(píng)論 0 1
  • 話說(shuō)碼字這回事兒,有的人樂(lè)在其中搓劫,有的人痛苦萬(wàn)分瞧哟,有的人當(dāng)做任務(wù),有的人當(dāng)做吐槽...... 近來(lái)有幾次看到孩子在...
    陳穎_樂(lè)嘉媽媽閱讀 268評(píng)論 3 3