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

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

聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序

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

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

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

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

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

前提

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

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

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

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

添加 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中只有一個方法,但是它會根據(jù)參數(shù)值的不同,會作出不同的處理:一種是正常返回一個對象,一種是拋出異常(因為我們要測試@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類內(nèi)部的 advice 將按照以下的順序進行執(zhí)行:

正常情況:

聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序

異常情況:

聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序

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

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

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

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。但是現(xiàn)在 aspect1 和 aspect2 都會攔截該controller中的方法。

下面繼續(xù)進行測試!

測試 正常情況

在瀏覽器直接輸入以下的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 先執(zhí)行。

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

[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 的執(zhí)行順序是未知的。那怎么解決呢?不急,下面會給出解決方案。

測試 異常情況

在瀏覽器中直接輸入以下的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 的執(zhí)行順序也是未定的。

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

方法有兩種:

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

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

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

比如,我們?yōu)?apsect1 和 aspect2 分別添加 @Order 注解,如下:

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

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

如下圖所示:

聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序

注意點

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

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

比如,我們假設正常情況下,執(zhí)行順序為”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

從結果可以發(fā)現(xiàn), Controller 中的 接口 未被執(zhí)行,aspect1 中的 @Before advice 也未被執(zhí)行。

參考資料

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

其中,AOP的執(zhí)行順序章節(jié)為: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.

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

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品国产www456c0m| 国产一级久久| 久久亚洲欧洲| 国产精品99精品一区二区三区∴| 99在线|亚洲一区二区| 香蕉精品视频在线观看| 亚洲无线观看| 999久久久精品国产| 国产毛片精品| 免费视频最近日韩| 在线观看亚洲精品福利片| 日韩欧美中文字幕在线视频| 天堂√中文最新版在线| 老司机精品在线| 五月天久久网站| 久久99青青| 免费国产亚洲视频| 亚洲成人va| 久久精品一区| 亚洲国产一区二区在线观看| 国产欧美日韩综合一区在线播放| 欧美一区二区性| 蜜桃一区二区三区在线| 国产乱码精品一区二区三区亚洲人 | 最新亚洲激情| 麻豆精品在线视频| 日本在线不卡视频一二三区| 欧美一区在线观看视频| 久久97视频| 日韩精品麻豆| 亚洲大片在线| 日韩av网站免费在线| 国产极品久久久久久久久波多结野| 免费一级欧美片在线观看网站| 国产不卡人人| 免费日韩精品中文字幕视频在线| 欧美日韩亚洲一区三区| 激情久久99| 黄色日韩在线| 国产精品亚洲人成在99www| 国产不卡一区| 亚洲一区网站| 国产日产精品一区二区三区四区的观看方式 | 日韩av在线免费观看不卡| 国产精品亚洲四区在线观看 | 久久精品国产大片免费观看| 综合一区二区三区| 国产66精品| 巨乳诱惑日韩免费av| 久久一区精品| 亚洲免费中文| 麻豆精品视频在线| 激情综合激情| 国产精品久久久久久久久免费高清 | 欧美另类中文字幕| 久久黄色影院| 日本成人中文字幕在线视频| 国产91欧美| 天堂va欧美ⅴa亚洲va一国产| 麻豆视频在线看| 亚洲人成亚洲精品| 伊人久久国产| 日韩国产欧美一区二区三区| 亚洲免费福利| 日韩在线麻豆| 四虎884aa成人精品最新| 日本不卡一区二区三区| 久久久久久久久丰满| 国产欧美88| 丝袜亚洲另类欧美| 日韩欧美一区二区三区免费观看| 欧美日韩黄网站| 亚洲二区免费| 国产一区二区三区久久久久久久久| 蜜臀av性久久久久蜜臀aⅴ流畅 | 99久久精品网站| 国产精品网在线观看| 中文日韩欧美| 蜜桃av在线播放| 麻豆一区二区在线| 日本一区二区中文字幕| 欧美精品一区二区三区精品| 欧美精品97| 一区二区三区国产在线| 99久久夜色精品国产亚洲1000部| 欧美韩一区二区| 亚洲人www| 亚洲精品中文字幕乱码| 日本一区二区免费高清| 欧美亚洲福利| 日韩在线网址| 最新亚洲国产| 免费日韩av片| 蜜桃成人av| 日韩欧美二区| 国产aⅴ精品一区二区四区| 欧美日韩在线精品一区二区三区激情综合| 性欧美精品高清| 欧美日韩尤物久久| av综合电影网站| 精品国产亚洲日本| 久久av免费| 欧美中文高清| 日韩一区网站| 亚洲一区av| 玖玖精品视频| 麻豆成人在线| 亚洲欧美久久| 日韩一级精品| aa国产精品| 亚洲黄页一区| 日韩午夜在线| 性一交一乱一区二区洋洋av| 国产在线成人| 不卡一区综合视频| 激情综合自拍| 一区免费视频| 影音先锋久久| 蜜桃av一区二区在线观看| 女主播福利一区| 一区久久精品| 天堂成人国产精品一区| 免费日韩av片| 亚洲乱亚洲高清| 91福利精品在线观看| 青青伊人久久| 国产精品欧美大片| 麻豆极品一区二区三区| 国产欧美69| 精品国产aⅴ| 亚洲一区资源| 国精品一区二区三区| 亚洲精品a级片| 六月婷婷一区| 欧美一区二区三区久久精品| 国产一精品一av一免费爽爽| 国产精品乱战久久久| 丁香婷婷久久| 99精品视频精品精品视频| 午夜欧美在线| 亚洲精品精选| 国产美女亚洲精品7777| 精品国产一区二| 国产suv精品一区| 久久精品二区三区| 国产免费成人| 7m精品国产导航在线| 久久精品女人| 久久视频一区| 老司机精品久久| 欧美一级一区| 高清久久精品| 中文字幕系列一区| 蘑菇福利视频一区播放| 日本91福利区| 成人午夜亚洲| 欧美日韩国产亚洲一区| 亚洲精品动态| 国产日本久久| 成人av三级| 蜜乳av另类精品一区二区| 欧美一级二级三级视频| 色欧美自拍视频| 日韩一级精品| 国产精一区二区| 亚洲伦乱视频| 亚洲美女91| 国产精品xx| 三级亚洲高清视频| 麻豆精品视频在线| 婷婷激情综合| 日本a级不卡| 日韩欧美另类一区二区| 亚洲免费观看| 国产精品99久久免费观看| 99久久夜色精品国产亚洲1000部| 在线免费观看亚洲| 久久久久久亚洲精品美女| 午夜欧美视频| 国产精品巨作av| 99成人在线| 久久字幕精品一区| 亚洲精品电影| 国产乱码精品| 欧美特黄一区| 免费一级欧美在线观看视频| 五月天综合网站| 国产精品成人国产| 国产一区清纯| 欧美经典一区| 男女激情视频一区| а√在线中文在线新版| 日韩欧美另类中文字幕| 欧美成人基地 | 国产欧美精品久久| 亚洲手机视频| 国产精品地址| 午夜在线观看免费一区| 国产精品黑丝在线播放| 亚洲毛片在线|