SpringBoot之AOP

一鸠踪、AOP概念

AOP(Aspect Oriented Programming)是一種編程范式港柜。請看大佬的總結(jié) AOP的簡介

常用術(shù)語

切面(Aspect):

一個關(guān)注點的模塊化,這個關(guān)注點可能會橫切多個對象。事務(wù)管理是J2EE應(yīng)用中一個關(guān)于橫切關(guān)注點的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式來實現(xiàn)饼灿。

連接點(Joinpoint):

程序執(zhí)行過程中某個特定的點,比如某方法調(diào)用或者處理異常

通知(Advice):

切面連接點的處理邏輯帝美,也就是向連接點注入的代碼碍彭。許多AOP框架(包括Spring)都是以攔截器做通知模型,并維護一個以連接點為中心的攔截器鏈悼潭。

@Before:?標識一個前置增強方法硕旗,相當于BeforeAdvice的功能.

@After:?final增強,不管是拋出異撑穑或者正常退出都會執(zhí)行.

@AfterReturning:? 后置增強漆枚,似于AfterReturningAdvice, 方法正常退出時執(zhí)行.

@AfterThrowing:? 異常拋出增強,相當于ThrowsAdvice.

@Around: 環(huán)繞增強抵知,相當于MethodInterceptor.

切入點(Pointcut):

JoinPoint的集合墙基,是程序中需要注入Advice的位置的集合,指明Advice要在什么樣的條件下才能被觸發(fā)刷喜,在程序中主要體現(xiàn)為書寫切入點表達式残制。

引入(Introduction):

用來給一個類型聲明額外的方法或?qū)傩裕ㄒ脖环Q為連接類型聲明(inter-type declaration))。Spring允許引入新的接口(以及一個對應(yīng)的實現(xiàn))到任何被代理的對象掖疮。例如初茶,你可以使用引入來使一個bean實現(xiàn)IsModified接口,以便簡化緩存機制浊闪。

目標對象(Target Object):

被一個或者多個切面所通知的對象恼布。也被稱做被通知(advised)對象。既然Spring AOP是通過運行時代理實現(xiàn)的搁宾,這個對象永遠是一個被代理(proxied)對象折汞。

AOP代理(AOP Proxy):

AOP框架創(chuàng)建的對象,用來實現(xiàn)切面契約(例如通知方法執(zhí)行等等)盖腿。在Spring中爽待,AOP代理可以是JDK動態(tài)代理或者CGLIB代理损同。

織入(Weaving):

把切面連接到其它的應(yīng)用程序類型或者對象上,并創(chuàng)建一個被通知的對象鸟款。這些可以在編譯時(例如使用AspectJ編譯器)膏燃,類加載時和運行時完成。Spring和其他純Java AOP框架一樣何什,在運行時完成織入组哩。

二、AOP的實現(xiàn)

1富俄、定義切面類

① 在類上使用 @Component 注解 把切面類加入到IOC容器中

② 在類上使用 @Aspect 注解 使之成為切面類


@Component

@Aspect

public class WebLogAspect {

}


2、定義切入點

定義方式:

execution:用于匹配方法執(zhí)行的連接點而咆;

within:用于匹配指定類型內(nèi)的方法執(zhí)行霍比;

this:用于匹配當前AOP代理對象類型的執(zhí)行方法;注意是AOP代理對象的類型匹配暴备,這樣就可能包括引入接口也類型匹配悠瞬;????????

target:用于匹配當前目標對象類型的執(zhí)行方法;注意是目標對象的類型匹配涯捻,這樣就不包括引入接口也類型匹配浅妆;

args:用于匹配當前執(zhí)行的方法傳入的參數(shù)為指定類型的執(zhí)行方法;

@within:用于匹配所以持有指定注解類型內(nèi)的方法障癌;

@target:用于匹配當前目標對象類型的執(zhí)行方法凌外,其中目標對象持有指定的注解;

@args:用于匹配當前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行涛浙;

@annotation:用于匹配當前執(zhí)行方法持有指定注解的方法康辑;

建議使用@annotation,配合自定義注解轿亮,實現(xiàn)攔截


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface WebLogAspect {

}


@Pointcut("@annotation(com.zgn.blog.annotation.WebLogAspect)")

public void webLog(){}


三疮薇、AOP的通知

1、前置通知@Before

除非拋出異常我注,否則這個通知不能阻止連接點之前的執(zhí)行流程

1)通過JoinPoint可以獲得通知的簽名信息按咒,如目標方法名、目標方法參數(shù)信息等

2)通過RequestContextHolder來獲取請求信息但骨,Session信息


@Before("webLog()")

public void doBefore(JoinPoint joinPoint)? throws Throwable{

? ? //獲取目標方法的參數(shù)信息?

? ? Object[] obj = joinPoint.getArgs();?

? ? //AOP代理類的信息?

? ? joinPoint.getThis();?

? ? //代理的目標對象?

? ? joinPoint.getTarget();?

? ? //用的最多 通知的簽名?

? ? Signature signature = joinPoint.getSignature();?

? ? //代理的是哪一個方法?

? ? logger.info("代理的是哪一個方法"+signature.getName());?

? ? //AOP代理類的名字?

? ? logger.info("AOP代理類的名字"+signature.getDeclaringTypeName());?

? ? //AOP代理類的類(class)信息?

? ? signature.getDeclaringType();?

? ? //獲取RequestAttributes?

? ? RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();?

? ? //從獲取RequestAttributes中獲取HttpServletRequest的信息?

? ? HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);?

? ? //如果要獲取Session信息的話励七,可以這樣寫:?

? ? //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);?

? ? //獲取請求參數(shù)

? ? Enumeration<String> enumeration = request.getParameterNames();?

? ? Map<String,String> parameterMap = Maps.newHashMap();?

? ? while (enumeration.hasMoreElements()){?

? ? ? ? String parameter = enumeration.nextElement();?

? ? ? ? parameterMap.put(parameter,request.getParameter(parameter));?

? ? }?

? ? String str = JSON.toJSONString(parameterMap);?

? ? if(obj.length > 0) {?

? ? ? ? logger.info("請求的參數(shù)信息為:"+str);

? ? }?

}


2、后置返回通知

1)如果參數(shù)中的第一個參數(shù)為JoinPoint奔缠,則第二個參數(shù)為返回值的信息

2)? 如果參數(shù)中的第一個參數(shù)不為JoinPoint呀伙,則第一個參數(shù)為returning中對應(yīng)的參數(shù)

3)? returning:限定了只有目標方法返回值與通知方法相應(yīng)參數(shù)類型時才能執(zhí)行后置返回通知,否則不執(zhí)行添坊,

4)? 對于returning對應(yīng)的通知方法參數(shù)為Object類型將匹配任何目標返回值


@AfterReturning(value = "webLog()",returning = "keys")?

public void doAfterReturning(JoinPoint joinPoint,Object keys){?

? ? log.info("第一個后置返回通知的返回值:"+keys);?

}?

@AfterReturning(value = "webLog()",returning = "keys",argNames = "keys")?

public void doAfterReturning(String keys){?

? ? log.info("第二個后置返回通知的返回值:"+keys);?

}


3剿另、后置異常通知

定義一個名字,該名字用于匹配通知實現(xiàn)方法的一個參數(shù)名,當目標方法拋出異常返回后雨女,將把目標方法拋出的異常傳給通知方法谚攒;

throwing:限定了只有目標方法拋出的異常與通知方法相應(yīng)參數(shù)異常類型時才能執(zhí)行后置異常通知,否則不執(zhí)行氛堕,

對于throwing對應(yīng)的通知方法參數(shù)為Throwable類型將匹配任何異常馏臭。


@AfterThrowing(value = "webLog()",throwing = "exception")?

public void doAfterThrowing(JoinPoint joinPoint,Throwable exception){?

? ? if(exception instanceof NullPointerException){?

? ? ? ? logger.info("空指針異常");?

? ? }?

}?


4、后置最終通知

后置最終通知(目標方法只要執(zhí)行完了就會執(zhí)行后置通知方法)


@After(value = "webLog()")?

public void doAfter(JoinPoint joinPoint){

? ? log.info("doAfter success");?

}?


5讼稚、環(huán)繞通知

1)第一個參數(shù)必須是ProceedingJoinPoint類型括儒。

2)在通知體內(nèi)調(diào)用ProceedingJoinPoint的proceed()方法會導致后臺的連接點方法執(zhí)行

3)proceed()方法也可能會被調(diào)用并且傳入一個Object[]對象,該數(shù)組中的值將被作為方法執(zhí)行時的入?yún)ⅰ?/p>



@Around(value = "webLog()")?

public Object doAround(ProceedingJoinPoint joinPoint){?

? ? try {?

? ? ? ? Object obj = joinPoint.proceed();?

? ? ? ? return obj;?

? ? } catch (Throwable e) {?

? ? ? ? e.printStackTrace();?

? ? }?

? ? return null;?

}?


參考文章:

https://blog.csdn.net/zhaoyanjun6/article/details/80669022

https://blog.csdn.net/lmb55/article/details/82470388

https://www.cnblogs.com/lic309/p/4079194.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锐想,一起剝皮案震驚了整個濱河市帮寻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赠摇,老刑警劉巖固逗,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異藕帜,居然都是意外死亡烫罩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門洽故,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贝攒,“玉大人,你說我怎么就攤上這事时甚《稣猓” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵撞秋,是天一觀的道長长捧。 經(jīng)常有香客問我,道長吻贿,這世上最難降的妖魔是什么串结? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮舅列,結(jié)果婚禮上肌割,老公的妹妹穿的比我還像新娘。我一直安慰自己帐要,他們只是感情好把敞,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著榨惠,像睡著了一般奋早。 火紅的嫁衣襯著肌膚如雪盛霎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天耽装,我揣著相機與錄音愤炸,去河邊找鬼。 笑死掉奄,一個胖子當著我的面吹牛规个,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姓建,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼诞仓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了速兔?” 一聲冷哼從身側(cè)響起墅拭,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎憨栽,沒想到半個月后帜矾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翼虫,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡屑柔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了珍剑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掸宛。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖招拙,靈堂內(nèi)的尸體忽然破棺而出唧瘾,到底是詐尸還是另有隱情,我是刑警寧澤别凤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布饰序,位于F島的核電站,受9級特大地震影響规哪,放射性物質(zhì)發(fā)生泄漏求豫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一诉稍、第九天 我趴在偏房一處隱蔽的房頂上張望蝠嘉。 院中可真熱鬧,春花似錦杯巨、人聲如沸蚤告。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杜恰。三九已至获诈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箫章,已是汗流浹背烙荷。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留檬寂,地道東北人终抽。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像桶至,于是被迫代替她去往敵國和親昼伴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356