日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring AOP详解一文搞懂@Aspect、@Pointcut、@Before、@Around、@After、@AfterReturning、@AfterThrowing

發布時間:2025/3/19 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring AOP详解一文搞懂@Aspect、@Pointcut、@Before、@Around、@After、@AfterReturning、@AfterThrowing 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 1、AOP是什么
        • 2、AOP中注解的含義
        • 3、Pointcut切入點的語法
        • 4、AOP代碼實現

1、AOP是什么

AOP:Aspect Oriented Programming,翻譯過來就是大名鼎鼎的“面向切面編程”,它是對面向對象的一種補充和完善。
AOP的使用場景一般有:數據源切換、事務管理、權限控制、日志打印等。根據它的名字我們不難理解,它的實現很像是將我們要實現的代碼切入業務實現的邏輯中。它有以下特點:
1、侵入性小,幾乎可以不改動原來邏輯的情況下把新的邏輯加入業務。
2、實現方便,使用幾個注解就可以實現,使系統更容易擴展。
3、更好的復用代碼,比如事務日志打印,簡單邏輯適合所有情況。

相關代碼請參考: chapter-4-springmvc-sourcecode-analysis
https://gitee.com/leo825/spring-framework-learning-example.git

2、AOP中注解的含義

@Aspect:切面。表示一個橫切進業務的一個對象。它里面包含切入點(Pointcut)和Advice(通知)。
@Pointcut:切入點。表示需要切入的位置,比如某些類或者某些方法,也就是先定一個范圍。
@Before:Advice(通知)的一種,切入點的方法體執行之前執行。
@Around:Advice(通知)的一種,環繞切入點執行也就是把切入點包裹起來執行。
@After:Advice(通知)的一種,在切入點正常運行結束后執行。
@AfterReturning:Advice(通知)的一種,在切入點正常運行結束后執行,異常則不執行
@AfterThrowing:Advice(通知)的一種,在切入點運行異常時執行。

3、Pointcut切入點的語法

語法規則如下代碼中注釋所示:

/*** 1、使用within表達式匹配* 下面示例表示匹配com.leo.controller包下所有的類的方法*/@Pointcut("within(com.leo.controller..*)")public void pointcutWithin(){}/*** 2、this匹配目標指定的方法,此處就是HelloController的方法*/@Pointcut("this(com.leo.controller.HelloController)")public void pointcutThis(){}/*** 3、target匹配實現UserInfoService接口的目標對象*/@Pointcut("target(com.leo.service.UserInfoService)")public void pointcutTarge(){}/*** 4、bean匹配所有以Service結尾的bean里面的方法,* 注意:使用自動注入的時候默認實現類首字母小寫為bean的id*/@Pointcut("bean(*ServiceImpl)")public void pointcutBean(){}/*** 5、args匹配第一個入參是String類型的方法*/@Pointcut("args(String, ..)")public void pointcutArgs(){}/*** 6、@annotation匹配是@Controller類型的方法*/@Pointcut("@annotation(org.springframework.stereotype.Controller)")public void pointcutAnnocation(){}/*** 7、@within匹配@Controller注解下的方法,要求注解的@Controller級別為@Retention(RetentionPolicy.CLASS)*/@Pointcut("@within(org.springframework.stereotype.Controller)")public void pointcutWithinAnno(){}/*** 8、@target匹配的是@Controller的類下面的方法,要求注解的@Controller級別為@Retention(RetentionPolicy.RUNTIME)*/@Pointcut("@target(org.springframework.stereotype.Controller)")public void pointcutTargetAnno(){}/*** 9、@args匹配參數中標注為@Sevice的注解的方法*/@Pointcut("@args(org.springframework.stereotype.Service)")public void pointcutArgsAnno(){}/*** 10、使用excution表達式* execution(* modifier-pattern? //用于匹配public、private等訪問修飾符* ret-type-pattern //用于匹配返回值類型,不可省略* declaring-type-pattern? //用于匹配包類型* name-pattern(param-pattern) //用于匹配類中的方法,不可省略* throws-pattern? //用于匹配拋出異常的方法* )** 下面的表達式解釋為:匹配com.leo.controller.HelloController類中以hello開頭的修飾符為public返回類型任意的方法*/@Pointcut(value = "execution(public * com.leo.controller.HelloController.hello*(..))")public void pointCut() {}

需要注意:上面的匹配的類型中支持或(||)與(&&)非(!)運算。

4、AOP代碼實現

首先配置pox.xml進行注解jar包的支持

<!-- aop aspect注解導包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency>

然后在配置文件中啟動注解支持,例如我的是myspringmvc-servlet.xml文件,這里需要注意的是注解要跟配置文件在一塊,舉個例子:如果需要切入Controller的配置就需要在myspringmvc-servlet.xml中添加,如果是切入應用的配置如Service則需要在applicationContext.xml中添加。

<!-- 開啟Aop注解 --><aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

Aop核心代碼如下:

ThreadLocal<Long> startTime = new ThreadLocal<>();/*** 10、使用excution表達式* execution(* modifier-pattern? //用于匹配public、private等訪問修飾符* ret-type-pattern //用于匹配返回值類型,不可省略* declaring-type-pattern? //用于匹配包類型* name-pattern(param-pattern) //用于匹配類中的方法,不可省略* throws-pattern? //用于匹配拋出異常的方法* )** 下面的表達式解釋為:匹配com.leo.controller.HelloController類中以hello開頭的修飾符為public返回類型任意的方法*/@Pointcut(value = "execution(public * com.leo.controller.HelloController.hello*(..))")public void pointCut() {}/*** 在方法執行之前執行** @param joinPoint*/@Before(value = "pointCut()")public void beforeLog(JoinPoint joinPoint) {System.out.println("進入LogAop的beforeLogger");startTime.set(System.currentTimeMillis());}/*** 在進入類之前執行,然后返回pjp.proceed()之前執行before,再執行方法體,在到after** @param*/@Around(value = "pointCut()")public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {System.out.println("進入LogAop的aroundLogger");return pjp.proceed();}/*** 在方法執行返回之后執行*/@After(value = "pointCut()")public void afterLog() {System.out.println("進入LogAop的afterLogger");long start = startTime.get();System.out.println("方法體執行耗時:" + (System.currentTimeMillis() - start) + "ms");startTime.remove();}/*** 在返回之后執行* @param o*/@AfterReturning(value = "pointCut()",returning = "o")public void afterRunningLog(Object o){System.out.println("進入LogAop的afterRunningLog");System.out.println(o.getClass());}/*** 在產生異常時執行*/@AfterThrowing(value = "pointCut()")public void afterThrowingLog(){System.out.println("進入LogAop的afterThrowingLog");}

開啟debug模式,查看各個標簽執行順序;
1、斷點進入@Around位置

2、執行完pjp.proceed()之后,開始進入@Before方法

3、執行完@Before中的方法后進入主方法

4、執行完主方法體,又回到了@Around的返回值

5、然后開始執行@After中內容

6.最后到了@AfterReturning方法體中

所以,正常的執行順序是:@Around ->@Before->主方法體->@Around中pjp.proceed()->@After->@AfterReturning

如果存下異常那執行順序是什么呢?以下模擬了一個異常。
1、首先進入了@Around的方法

2、進入了@After的方法

3、最后進入了@AfterThrowing的方法

因此如果異常在Around中pjp.proceed()之前,則執行順序為:@Around -> @After -> @AfterThrowing

同理,如果異常在Around中pjp.proceed()之后,則執行順序為@Around ->@Before->主方法體->@Around中pjp.proceed()->@After->@AfterThrowing*

總結

以上是生活随笔為你收集整理的Spring AOP详解一文搞懂@Aspect、@Pointcut、@Before、@Around、@After、@AfterReturning、@AfterThrowing的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。