日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

聊聊Spring AOP @Before @Around @After等advice的執行順序

瀏覽:141日期:2023-07-22 17:04:48

用過spring框架進行開發的人,多多少少會使用過它的AOP功能,都知道有@Before、@Around和@After等advice。

最近,為了實現項目中的輸出日志和權限控制這兩個需求,我也使用到了AOP功能。

我使用到了@Before、@Around這兩個advice。但在,使用過程中,卻對它們的執行順序并不清楚。

為了弄清楚在不同情況下,這些advice到底是以怎么樣的一個順序進行執行的,我作了個測試,在此將其記錄下來,以供以后查看。

前提

對于AOP相關類(aspect、pointcut等)的概念,本文不作說明。

對于如何讓spring框架掃描到AOP,本文也不作說明。

情況一: 一個方法只被一個Aspect類攔截

當一個方法只被一個Aspect攔截時,這個Aspect中的不同advice是按照怎樣的順序進行執行的呢?請看:

添加 PointCut類

該pointcut用來攔截test包下的所有類中的所有方法。

package test;import org.aspectj.lang.annotation.Pointcut;public class PointCuts { @Pointcut(value = 'within(test.*)') public void aopDemo() { }}添加Aspect類

該類中的advice將會用到上面的pointcut,使用方法請看各個advice的value屬性。

package test;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component@Aspectpublic class Aspect1 { @Before(value = 'test.PointCuts.aopDemo()') public void before(JoinPoint joinPoint) { System.out.println('[Aspect1] before advise'); } @Around(value = 'test.PointCuts.aopDemo()') public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println('[Aspect1] around advise 1'); pjp.proceed(); System.out.println('[Aspect1] around advise2'); } @AfterReturning(value = 'test.PointCuts.aopDemo()') public void afterReturning(JoinPoint joinPoint) { System.out.println('[Aspect1] afterReturning advise'); } @AfterThrowing(value = 'test.PointCuts.aopDemo()') public void afterThrowing(JoinPoint joinPoint) { System.out.println('[Aspect1] afterThrowing advise'); } @After(value = 'test.PointCuts.aopDemo()') public void after(JoinPoint joinPoint) { System.out.println('[Aspect1] after advise'); }}添加測試用Controller

添加一個用于測試的controller,這個controller中只有一個方法,但是它會根據參數值的不同,會作出不同的處理:一種是正常返回一個對象,一種是拋出異常(因為我們要測試@AfterThrowing這個advice)

package test;import test.exception.TestException;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping(value = '/aop')public class AopTestController { @ResponseStatus(HttpStatus.OK) @RequestMapping(value = '/test', method = RequestMethod.GET) public Result test(@RequestParam boolean throwException) { // case 1 if (throwException) { System.out.println('throw an exception'); throw new TestException('mock a server exception'); } // case 2 System.out.println('test OK'); return new Result() {{ this.setId(111); this.setName('mock a Result'); }}; } public static class Result { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }}

測試 正常情況

在瀏覽器直接輸入以下的URL,回車:

http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false

我們會看到輸出的結果是:

[Aspect1] around advise 1[Aspect1] before advisetest OK[Aspect1] around advise2[Aspect1] after advise[Aspect1] afterReturning advise

測試 異常情況

在瀏覽器中直接輸入以下的URL,回車:

http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true

我們會看到輸出的結果是:

[Aspect1] around advise 1[Aspect1] before advisethrow an exception[Aspect1] after advise[Aspect1] afterThrowing advise結論

在一個方法只被一個aspect類攔截時,aspect類內部的 advice 將按照以下的順序進行執行:

正常情況:

聊聊Spring AOP @Before @Around @After等advice的執行順序

異常情況:

聊聊Spring AOP @Before @Around @After等advice的執行順序

情況二: 同一個方法被多個Aspect類攔截

此處舉例為被兩個aspect類攔截。

有些情況下,對于兩個不同的aspect類,不管它們的advice使用的是同一個pointcut,還是不同的pointcut,都有可能導致同一個方法被多個aspect類攔截。那么,在這種情況下,這多個Aspect類中的advice又是按照怎樣的順序進行執行的呢?請看:

pointcut類保持不變

添加一個新的aspect類

package test;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component@Aspectpublic class Aspect2 { @Before(value = 'test.PointCuts.aopDemo()') public void before(JoinPoint joinPoint) { System.out.println('[Aspect2] before advise'); } @Around(value = 'test.PointCuts.aopDemo()') public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println('[Aspect2] around advise 1'); pjp.proceed(); System.out.println('[Aspect2] around advise2'); } @AfterReturning(value = 'test.PointCuts.aopDemo()') public void afterReturning(JoinPoint joinPoint) { System.out.println('[Aspect2] afterReturning advise'); } @AfterThrowing(value = 'test.PointCuts.aopDemo()') public void afterThrowing(JoinPoint joinPoint) { System.out.println('[Aspect2] afterThrowing advise'); } @After(value = 'test.PointCuts.aopDemo()') public void after(JoinPoint joinPoint) { System.out.println('[Aspect2] after advise'); }}

測試用Controller也不變

還是使用上面的那個Controller。但是現在 aspect1 和 aspect2 都會攔截該controller中的方法。

下面繼續進行測試!

測試 正常情況

在瀏覽器直接輸入以下的URL,回車:

http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false

我們會看到輸出的結果是:

[Aspect2] around advise 1[Aspect2] before advise[Aspect1] around advise 1[Aspect1] before advisetest OK[Aspect1] around advise2[Aspect1] after advise[Aspect1] afterReturning advise[Aspect2] around advise2[Aspect2] after advise[Aspect2] afterReturning advise

但是這個時候,我不能下定論說 aspect2 肯定就比 aspect1 先執行。

不信?你把服務務器重新啟動一下,再試試,說不定你就會看到如下的執行結果:

[Aspect1] around advise 1[Aspect1] before advise[Aspect2] around advise 1[Aspect2] before advisetest OK[Aspect2] around advise2[Aspect2] after advise[Aspect2] afterReturning advise[Aspect1] around advise2[Aspect1] after advise[Aspect1] afterReturning advise

也就是說,這種情況下, aspect1 和 aspect2 的執行順序是未知的。那怎么解決呢?不急,下面會給出解決方案。

測試 異常情況

在瀏覽器中直接輸入以下的URL,回車:

http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true

我們會看到輸出的結果是:

[Aspect2] around advise 1[Aspect2] before advise[Aspect1] around advise 1[Aspect1] before advisethrow an exception[Aspect1] after advise[Aspect1] afterThrowing advise[Aspect2] after advise[Aspect2] afterThrowing advise

同樣地,如果把服務器重啟,然后再測試的話,就可能會看到如下的結果:

[Aspect1] around advise 1[Aspect1] before advise[Aspect2] around advise 1[Aspect2] before advisethrow an exception[Aspect2] after advise[Aspect2] afterThrowing advise[Aspect1] after advise[Aspect1] afterThrowing advise

也就是說,同樣地,異常情況下, aspect1 和 aspect2 的執行順序也是未定的。

那么在 情況二 下,如何指定每個 aspect 的執行順序呢?

方法有兩種:

實現org.springframework.core.Ordered接口,實現它的getOrder()方法

給aspect添加@Order注解,該注解全稱為:org.springframework.core.annotation.Order

不管采用上面的哪種方法,都是值越小的 aspect 越先執行。

比如,我們為 apsect1 和 aspect2 分別添加 @Order 注解,如下:

@Order(5)@Component@Aspectpublic class Aspect1 { // ...}@Order(6)@Component@Aspectpublic class Aspect2 { // ...}

這樣修改之后,可保證不管在任何情況下, aspect1 中的 advice 總是比 aspect2 中的 advice 先執行。

如下圖所示:

聊聊Spring AOP @Before @Around @After等advice的執行順序

注意點

如果在同一個 aspect 類中,針對同一個 pointcut,定義了兩個相同的 advice(比如,定義了兩個 @Before),那么這兩個 advice 的執行順序是無法確定的,哪怕你給這兩個 advice 添加了 @Order 這個注解,也不行。這點切記。

對于@Around這個advice,不管它有沒有返回值,但是必須要方法內部,調用一下 pjp.proceed();否則,Controller 中的接口將沒有機會被執行,從而也導致了 @Before這個advice不會被觸發。

比如,我們假設正常情況下,執行順序為”aspect2 -> apsect1 -> controller”,如果,我們把 aspect1中的@Around中的 pjp.proceed();給刪掉,那么,我們看到的輸出結果將是:

[Aspect2] around advise 1[Aspect2] before advise[Aspect1] around advise 1[Aspect1] around advise2[Aspect1] after advise[Aspect1] afterReturning advise[Aspect2] around advise2[Aspect2] after advise[Aspect2] afterReturning advise

從結果可以發現, Controller 中的 接口 未被執行,aspect1 中的 @Before advice 也未被執行。

參考資料

Spring 4.3.2.RELEASE 官方資料:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

其中,AOP的執行順序章節為:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-ataspectj-advice-ordering

Advice ordering

What happens when multiple pieces of advice all want to run at the same join point?

Spring AOP follows the same precedence rules as AspectJ to determine the order of advice execution.

The highest precedence advice runs first 'on the way in' (so given two pieces of before advice, the one with highest precedence runs first).

'On the way out' from a join point, the highest precedence advice runs last (so given two pieces of after advice, the one with the highest precedence will run second).

When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined.

You can control the order of execution by specifying precedence.

This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation.

Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.

When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the declaration order via reflection for javac-compiled classes).

Consider collapsing such advice methods into one advice method per join point in each aspect class, or refactor the pieces of advice into separate aspect classes - which can be ordered at the aspect level.

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。如有錯誤或未考慮完全的地方,望不吝賜教。

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
成人福利av| 国产精品男女| 欧美激情一区| 日本亚州欧洲精品不卡| 一本色道久久精品| 麻豆一区二区在线| 高清一区二区三区av| 久久av免费| 国产精品最新自拍| 亚洲精品乱码| 国产一级成人av| 美女网站久久| 国产亚洲激情| 亚洲综合电影一区二区三区| 石原莉奈在线亚洲三区| 亚洲激精日韩激精欧美精品| 亚洲一本视频| 天堂资源在线亚洲| 在线精品小视频| 久久高清国产| 亚洲精品一二三区区别| 亚洲天堂久久| 亚洲午夜精品久久久久久app| 国产中文字幕一区二区三区| 日韩国产网站| 性欧美69xoxoxoxo| 老牛影视一区二区三区| 国产日韩欧美| 亚洲欧美在线综合| 婷婷亚洲精品| 日韩一区三区| 69堂精品视频在线播放| 视频一区日韩| 国产日韩三级| 国产日韩欧美在线播放不卡| 国产精品成人自拍| 国产精品1区| 久久久天天操| 欧美一区=区| 亚洲综合婷婷| 欧美日韩中出| 黄色网一区二区| 日韩天堂在线| 国产免费成人| 亚洲永久精品唐人导航网址| 黑丝一区二区| 麻豆久久久久久| 麻豆国产精品| 欧美va天堂在线| 久久av在线| 国产精品成人**免费视频| 精品久久久网| 亚洲高清久久| 在线精品国产亚洲| av最新在线| 亚洲激情国产| 欧美日韩夜夜| 欧美日韩一二三四| 亚洲3区在线| 久久精品国产亚洲一区二区三区| 伊人久久av| 亚洲精品88| 欧美a级片一区| 日本免费新一区视频| 日本一二区不卡| 免费一区二区三区在线视频| 日韩精品一卡| 国产毛片精品| 石原莉奈在线亚洲二区| 电影亚洲精品噜噜在线观看| 国产亚洲观看| 91精品91| 亚洲精品成人图区| 国产日产一区| 免费人成在线不卡| 日韩欧美三级| 国产精品99久久免费| 亚洲精选av| 蜜桃成人av| 国产精品久久久久久久免费观看| 日韩成人在线看| 亚洲少妇在线| 日韩毛片在线| 精品久久97| 国产欧美一区二区色老头| 视频在线在亚洲| 99久久婷婷| 国产成人a视频高清在线观看| 欧美日本久久| 亚洲精品观看| 在线免费观看亚洲| 在线午夜精品| 久久一区二区中文字幕| 超碰成人av| 美女精品久久| 国产精品探花在线观看| 亚洲天堂日韩在线| 国产亚洲精品久久久久婷婷瑜伽| 国产一区二区三区久久| 国产精品丝袜在线播放| 日韩av一区二区三区四区| 亚洲欧美久久久| 欧美~级网站不卡| 免费观看久久av| 欧美~级网站不卡| 国产盗摄——sm在线视频| 日韩欧美美女在线观看| 亚洲精品在线影院| 国产精品网址| 日韩av午夜在线观看| 99精品国产一区二区三区| 亚洲福利专区| 欧美特黄视频| 91精品视频一区二区| 国产精品久久国产愉拍| 麻豆视频一区| 免费av一区二区三区四区| 亚洲va中文在线播放免费| 亚洲深夜视频| 韩国精品主播一区二区在线观看 | 欧美精品1区| 国产欧美三级| 国产成人免费| 亚洲国产福利| 高清av不卡| 久久久噜噜噜| 五月天综合网站| 国产美女一区| 亚洲一二av| 久久国产欧美日韩精品| 91精品麻豆| 国产精品一区二区精品| 美女毛片一区二区三区四区最新中文字幕亚洲 | 精品国产免费人成网站| 欧美粗暴jizz性欧美20| 麻豆精品久久| 日韩av成人高清| 欧美亚洲在线日韩| 综合国产精品| 99久久精品费精品国产| 黄色日韩在线| 国产日韩高清一区二区三区在线 | 国产精品一区二区免费福利视频| 日韩国产欧美在线播放| 国产精品毛片久久| 亚洲va久久| 美女毛片一区二区三区四区 | 日本色综合中文字幕| 免费看久久久| 亚洲大全视频| 欧美一级鲁丝片| 亚洲狼人精品一区二区三区| 麻豆精品蜜桃| 日韩精品中文字幕第1页| 国产精品videossex久久发布 | 欧美日韩免费看片| 久久久成人网| 日韩专区欧美专区| 欧美亚洲国产日韩| 国产一区二区三区日韩精品| 日韩精品诱惑一区?区三区| 黄色成人精品网站| 老牛影视一区二区三区| 欧美亚洲三级| 精品视频一二| 99久久亚洲精品| 亚洲在线网站| 国产精品115| 亚洲国产专区校园欧美| 丰满少妇一区| 国产亚洲网站| 日韩精品一区二区三区免费观影 | 在线观看视频免费一区二区三区| 日韩欧美美女在线观看| 久久中文欧美| 日本成人中文字幕在线视频| 婷婷亚洲综合| 亚洲成人av观看| 麻豆精品视频在线观看免费| 日韩视频中文| 日韩中文字幕91| 99国产精品私拍| 99国产精品久久久久久久成人热| 韩日一区二区| 国产日韩一区二区三区在线播放| 日韩精品一区第一页| 国产91欧美| 久久亚洲在线| 美女高潮久久久| 免费观看在线综合色| 亚洲精品免费观看| 久久国产精品美女| 久久国产亚洲| 91麻豆精品| 国产精品99一区二区| 石原莉奈在线亚洲二区| 精品九九在线| 美女被久久久| 中文在线а√在线8| 日韩国产欧美一区二区三区|