Spring Boot AOP

注:AOP稱為面向切面編程,在程序開發(fā)中常用來解決一些系統(tǒng)公共的問題筒繁,比如日志噩凹,事務(wù),權(quán)限攔截等等毡咏,本文主要講述Spring AOP的使用驮宴。

基本概念

1、Aspect(切面):通常是一個(gè)類呕缭,里面可以定義切入點(diǎn)和通知堵泽,比如Log類修己。
2、JointPoint(連接點(diǎn)):程序執(zhí)行過程中明確的點(diǎn)迎罗,即在哪個(gè)地方進(jìn)行攔截箩退。
3、Advice(通知):AOP在特定的切入點(diǎn)上執(zhí)行的增強(qiáng)處理佳谦,主要包括以下幾種方式:before,after,afterReturning,afterThrowing,around
(1)前置通知(Before):在目標(biāo)方法前調(diào)用戴涝。
(2)后置通知(After):在目標(biāo)方法后調(diào)用,無論是否有異常都執(zhí)行钻蔑。
(3)環(huán)繞通知(Around):將 Before 和 After 啥刻,甚至拋出增強(qiáng)和返回增強(qiáng)合到一起,即動(dòng)態(tài)代理功能一樣咪笑。
(4)返回通知(AfterReturning):在方法返回結(jié)果后執(zhí)行可帽,該增強(qiáng)可以接收到目標(biāo)方法返回結(jié)果,前提沒有異常的情況下窗怒。
(5)異常通知(AfterThrowing):在目標(biāo)方法拋出對應(yīng)的類型后執(zhí)行映跟,可以接收到對應(yīng)的異常信息,前提拋出異常的情況下扬虚。
4努隙、Pointcut(切入點(diǎn)):就是帶有通知的連接點(diǎn),在程序中主要體現(xiàn)為書寫切入點(diǎn)表達(dá)式
5辜昵、AOP代理:AOP框架創(chuàng)建的對象荸镊,代理就是目標(biāo)對象的加強(qiáng)。

具體實(shí)例

該實(shí)例功能堪置,在做除法運(yùn)算時(shí)躬存,將其日志打印輸出,具體代碼如下:

Calc.java 業(yè)務(wù)類

package com.itbofeng;
import org.springframework.stereotype.Service;
//核心業(yè)務(wù)邏輯類舀锨,保證業(yè)務(wù)邏輯類的功能單一岭洲,使用Spring Aop降低代碼的侵入性
@Service
public class Calc {
    //進(jìn)行觸發(fā)運(yùn)算功能
    public int div(int a, int b) {
        return a/b;
    }
}

Log.java 切面類:日志記錄

package com.itbofeng;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;

//切面類:日志記錄功能
@Aspect
@Component
public class Log {

    //切點(diǎn)
    @Pointcut("execution(public * com.itbofeng.*.*(..))")
    public void logPointCut(){}

    //前置通知
    @Before("logPointCut()")
    public void calcBefore(JoinPoint joinPoint){
        String name=joinPoint.getSignature().getName();
        Object [] args=joinPoint.getArgs();
        System.out.println("Log.calcBefore exec method "+name+",the args are"+ Arrays.asList(args));
    }
    //返回通知
    @AfterReturning(returning = "ret",pointcut = "logPointCut()")
    public void  calcAfterReturning(JoinPoint joinPoint,Object ret){
        String name=joinPoint.getSignature().getName();
        Object [] args=joinPoint.getArgs();
        System.out.println("Log.AfterReturning exec method "+name+",the args are"+ Arrays.asList(args)+",the result is "+ret);
    }

    //異常通知
    @AfterThrowing(pointcut="logPointCut()",throwing="e")
    public void  calcAfterThrowing(JoinPoint joinPoint,Exception e){
        String name=joinPoint.getSignature().getName();
        Object [] args=joinPoint.getArgs();
        System.out.println("Log.AfterThrowing exec method "+name+",the args are"+ Arrays.asList(args)+",the Exception is "+e.getMessage());
    }
    //后置通知
    @After("logPointCut()")
    public void calcAfter(JoinPoint joinPoint){
        String name=joinPoint.getSignature().getName();
        Object [] args=joinPoint.getArgs();
        System.out.println("Log.calcAfter exec method "+name+",the args are"+ Arrays.asList(args)+"....");
    }


    @Around("logPointCut()")
    public Object calcAround(ProceedingJoinPoint proceedingJoinPoint){
        //相當(dāng)于前置通知
        Object [] args=proceedingJoinPoint.getArgs();//參數(shù)
        System.out.println("Log.calcAround before...,the args are"+Arrays.asList(args));
        Object ret=null;
        try {
            ret=proceedingJoinPoint.proceed();//返回值
            //相當(dāng)于返回通知
            System.out.println("Log.calcAround AfterReturning...,the result is "+ret);
        } catch (Throwable e) {
            //相當(dāng)于異常通知
            System.out.println("Log.calcAround AfterThrowing..."+e.getMessage());
            e.printStackTrace();
        }finally {
            //相當(dāng)于后置通知
            System.out.println("Log.calcAround after...");
            return ret;
        }
    }
}

MainConfig.java 配置類

package com.itbofeng;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan
//開啟AspectJ自動(dòng)代理功能相當(dāng)于xml中的<aop:aspectj-autoproxy />
@EnableAspectJAutoProxy
//配置類:這里使用的是基于注解的方式,相當(dāng)于xml方式的配置文件
public class MainConfig {

}

AopApplicationTests.java 測試類

package com.itbofeng;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//測試類
public class AopApplicationTests {
    @Test
    public void testAop() throws Exception {
        ApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfig.class);
        Calc calc=applicationContext.getBean(Calc.class);
        calc.div(1,1);//改變這里為1/0可以測試異常情況下
    }
}

運(yùn)行結(jié)果:

運(yùn)行1:前提說明:先注釋環(huán)繞通知坎匿,運(yùn)行calc.div(1,1);正常情況下:

Log.calcBefore exec method div,the args are[1, 1]
Log.calcAfter exec method div,the args are[1, 1]....
Log.AfterReturning exec method div,the args are[1, 1],the result is 1

Process finished with exit code 0

運(yùn)行2:前提說明:先注釋環(huán)繞通知盾剩,運(yùn)行calc.div(1,0);異常情況下:

Log.calcBefore exec method div,the args are[1, 0]
Log.calcAfter exec method div,the args are[1, 0]....
Log.AfterThrowing exec method div,the args are[1, 0],the Exception is / by zero

java.lang.ArithmeticException: / by zero

運(yùn)行3:前提說明:先注釋除環(huán)繞外的其他通知,運(yùn)行calc.div(1,1);正常情況下:

Log.calcAround before...,the args are[1, 1]
Log.calcAround AfterReturning...,the result is 1
Log.calcAround after...

Process finished with exit code 0

運(yùn)行3:前提說明:先注釋除環(huán)繞外的其他通知碑诉,運(yùn)行calc.div(1,0);異常情況下:

Log.calcAround before...,the args are[1, 0]
Log.calcAround AfterThrowing.../ by zero
Log.calcAround after...
java.lang.ArithmeticException: / by zero

小結(jié):
本文主要講解了AOP中的基本概念彪腔,以及簡單的使用Spring AOP侥锦,主要是為了體驗(yàn)一下什么是AOP进栽,在本文中需要掌握以下三個(gè)方面:

1、AOP的理解:面向切面編程恭垦,是一種編程思想快毛,就像面向?qū)ο缶幊桃粯?Spring AOP只是一個(gè)具體的實(shí)現(xiàn)格嗅,就像Java是面向?qū)ο笳Z言一樣。

2唠帝、Spring AOP在應(yīng)用程序中應(yīng)用場景:在應(yīng)用程序中AOP主要承擔(dān)一些系統(tǒng)級(jí)別的功能也即一些通用的功能屯掖,如日志記錄,權(quán)限校驗(yàn)襟衰,錯(cuò)誤處理贴铜,事務(wù)控制等。

3瀑晒、注解的使用:需要掌握理解這些注解的使用绍坝,以及每個(gè)通知方法執(zhí)行時(shí)機(jī)。

最后:我這里有Spring苔悦、Spring Boot相關(guān)的視頻教程(由于各種原因轩褐,不方便在此公開,還請見諒玖详,不過這視頻是我見到我認(rèn)為最好的教程把介,不過教程也建議有過Spring使用經(jīng)驗(yàn)的朋友觀看,這樣效果會(huì)更加好蟋座,有好多地方會(huì)涉及原理講解拗踢,沒有使用過的話,壓力會(huì)有點(diǎn)大)向臀,我就是一邊沒事的時(shí)候看看教程秒拔,加上自己的理解,寫文章的飒硅,所以文章有誤的地方砂缩,還請大家指正,我一定會(huì)虛心學(xué)習(xí)的三娩,有需要視頻教程的朋友庵芭,可以私信我如果大家覺得文章不錯(cuò)雀监,點(diǎn)個(gè)贊双吆,關(guān)注一下,感謝你的支持会前。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末好乐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓦宜,更是在濱河造成了極大的恐慌蔚万,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件临庇,死亡現(xiàn)場離奇詭異反璃,居然都是意外死亡昵慌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門淮蜈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斋攀,“玉大人,你說我怎么就攤上這事梧田〈景” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵裁眯,是天一觀的道長肖方。 經(jīng)常有香客問我,道長未状,這世上最難降的妖魔是什么俯画? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮司草,結(jié)果婚禮上艰垂,老公的妹妹穿的比我還像新娘。我一直安慰自己埋虹,他們只是感情好猜憎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搔课,像睡著了一般胰柑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爬泥,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天柬讨,我揣著相機(jī)與錄音,去河邊找鬼袍啡。 笑死踩官,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的境输。 我是一名探鬼主播蔗牡,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嗅剖!你這毒婦竟也來了辩越?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤信粮,失蹤者是張志新(化名)和其女友劉穎黔攒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亏钩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年莲绰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欺旧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姑丑。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辞友,靈堂內(nèi)的尸體忽然破棺而出栅哀,到底是詐尸還是另有隱情,我是刑警寧澤称龙,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布留拾,位于F島的核電站,受9級(jí)特大地震影響鲫尊,放射性物質(zhì)發(fā)生泄漏痴柔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一疫向、第九天 我趴在偏房一處隱蔽的房頂上張望咳蔚。 院中可真熱鬧,春花似錦搔驼、人聲如沸谈火。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糯耍。三九已至,卻和暖如春囊嘉,著一層夾襖步出監(jiān)牢的瞬間温技,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工扭粱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荒揣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓焊刹,卻偏偏與公主長得像系任,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子虐块,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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

  • 本文小福利 點(diǎn)我獲取阿里云優(yōu)惠券 AOP核心概念 1俩滥、橫切關(guān)注點(diǎn) 對哪些方法進(jìn)行攔截,攔截后怎么處理贺奠,這些關(guān)注點(diǎn)稱...
    不想當(dāng)碼農(nóng)的程序員閱讀 1,839評(píng)論 0 8
  • AOP 代理的兩種實(shí)現(xiàn): jdk是代理接口霜旧,私有方法必然不會(huì)存在在接口里,所以就不會(huì)被攔截到; cglib是子類挂据,...
    xiaolyuh閱讀 2,751評(píng)論 0 8
  • AOP可用于添加日志以清、計(jì)算接口耗時(shí)等,大致過程: 1. 定義切面類 2. 定義切入點(diǎn) 3. 編寫處理方法 實(shí)例: ...
    Superwind20閱讀 1,690評(píng)論 0 0
  • 本章內(nèi)容: 面向切面編程的基本原理 通過POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,149評(píng)論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理崎逃,服務(wù)發(fā)現(xiàn)掷倔,斷路器,智...
    卡卡羅2017閱讀 134,665評(píng)論 18 139