SpringBoot如何使用@Aspect注解實現(xiàn)AOP
使用@Aspect 注解實現(xiàn)AOP
AOP(Aspect Oriented Programming,面向切面編程)是通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。
AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。
利用AOP可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
在Spring AOP中業(yè)務(wù)邏輯僅僅只關(guān)注業(yè)務(wù)本身,將日志記錄、性能統(tǒng)計、安全控制、事務(wù)處理、異常處理等代碼從業(yè)務(wù)邏輯代碼中劃分出來,從而在改變這些行為的時候不影響業(yè)務(wù)邏輯的代碼。
相關(guān)注解介紹
注解 | 作用 |
@Aspect | 把當前類標識為一個切面 |
@Pointcut | Pointcut是織入Advice的觸發(fā)條件。每個Pointcut的定義包括2部分,一是表達式,二是方法簽名。方法簽名必須是public及void型??梢詫ointcut中的方法看作是一個被Advice引用的助記符,因為表達式不直觀,因此我們可以通過方法簽名的方式為此表達式命名。因此Pointcut中的方法只需要方法簽名,而不需要在方法體內(nèi)編寫實際代碼。 |
@Around | 環(huán)繞增強,目標方法執(zhí)行前后分別執(zhí)行一些代碼 |
@AfterReturning | 返回增強,目標方法正常執(zhí)行完畢時執(zhí)行 |
@Before | 前置增強,目標方法執(zhí)行之前執(zhí)行 |
@AfterThrowing | 異常拋出增強,目標方法發(fā)生異常的時候執(zhí)行 |
@After | 后置增強,不管是拋出異?;蛘哒M顺龆紩?zhí)行 |
一、添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
二、編寫增強類
package com.wuychn.springbootaspect.aspect; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Aspect @Component @Slf4j public class LogAspect { /** * 前置增強:目標方法執(zhí)行之前執(zhí)行 * * @param jp */ @Before("execution(* com.wuychn.springbootaspect.controller.*.*(..))") // 所有controller包下面的所有方法的所有參數(shù) public void beforeMethod(JoinPoint jp) { String methodName = jp.getSignature().getName(); log.info("【前置增強】the method 【" + methodName + "】 begins with " + JSON.toJSONString(jp.getArgs())); } /** * 后置增強:目標方法執(zhí)行之后執(zhí)行以下方法體的內(nèi)容,不管是否發(fā)生異常。 * * @param jp */ @After("execution(* com.wuychn.springbootaspect.controller.*.*(..)))") public void afterMethod(JoinPoint jp) { log.info("【后置增強】this is a afterMethod advice..."); } /** * 返回增強:目標方法正常執(zhí)行完畢時執(zhí)行 * * @param jp * @param result */ @AfterReturning(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..)))", returning = "result") public void afterReturningMethod(JoinPoint jp, Object result) { String methodName = jp.getSignature().getName(); log.info("【返回增強】the method 【" + methodName + "】 ends with 【" + result + "】"); } /** * 異常增強:目標方法發(fā)生異常的時候執(zhí)行,第二個參數(shù)表示補貨異常的類型 * * @param jp * @param e */ @AfterThrowing(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..))", throwing = "e") public void afterThorwingMethod(JoinPoint jp, Exception e) { String methodName = jp.getSignature().getName(); log.error("【異常增強】the method 【" + methodName + "】 occurs exception: ", e); } /** * 環(huán)繞增強:目標方法執(zhí)行前后分別執(zhí)行一些代碼,發(fā)生異常的時候執(zhí)行另外一些代碼 * * @return */ /* @Around(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..))") public Object aroundMethod(ProceedingJoinPoint jp) { String methodName = jp.getSignature().getName(); Object result = null; try { log.info("【環(huán)繞增強中的--->前置增強】:the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs())); //執(zhí)行目標方法 result = jp.proceed(); log.info("【環(huán)繞增強中的--->返回增強】:the method 【" + methodName + "】 ends with " + result); } catch (Throwable e) { result = "error"; log.info("【環(huán)繞增強中的--->異常增強】:the method 【" + methodName + "】 occurs exception " + e); } log.info("【環(huán)繞增強中的--->后置增強】:-----------------end.----------------------"); return result; }*/ }
三、Controller
package com.wuychn.springbootaspect.controller; import com.wuychn.springbootaspect.entity.User; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class TestController { @GetMapping("/doNormal") public String doNormal(String name, String age, User user) { log.info("【執(zhí)行方法】:doNormal"); return "doNormal"; } @GetMapping("/doWithException") public String doWithException(String name, String age, User user) { log.info("【執(zhí)行方法】:doWithException"); int a = 1 / 0; return "doWithException"; } }
啟動程序,當訪問doNormal方法時,
日志輸出如下:
2019-05-13 14:36:20.931 INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect : 【前置通知】the method 【doNormal】 begins with ["zhangsan","12",{"address":["chengdu","beijing"],"name":"zhangsan"}]
2019-05-13 14:36:20.932 INFO 12592 --- [nio-9379-exec-5] c.w.s.controller.TestController : 【執(zhí)行方法】:doNormal
2019-05-13 14:36:20.932 INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect : 【后置通知】this is a afterMethod advice...
2019-05-13 14:36:20.932 INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect : 【返回通知】the method 【doNormal】 ends with 【doNormal】
當訪問doWithException方法時,
日志輸出如下:
2019-05-13 14:45:03.699 INFO 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect : 【前置通知】the method 【doWithException】 begins with ["zhangsan","12",{"address":["chengdu","beijing"],"name":"zhangsan"}]
2019-05-13 14:45:03.699 INFO 12592 --- [nio-9379-exec-8] c.w.s.controller.TestController : 【執(zhí)行方法】:doWithException
2019-05-13 14:45:03.699 INFO 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect : 【后置通知】this is a afterMethod advice...
2019-05-13 14:45:03.704 ERROR 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect : 【異常通知】the method 【doWithException】 occurs exception:
java.lang.ArithmeticException: / by zero
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot2零基礎(chǔ)到精通之數(shù)據(jù)與頁面響應(yīng)
SpringBoot是一種整合Spring技術(shù)棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架2022-03-03詳解Java編程中protected修飾符與static修飾符的作用
這篇文章主要介紹了Java編程中protected關(guān)鍵字與static關(guān)鍵字的作用,是Java入門學習中的基礎(chǔ)知識,需要的朋友可以參考下2016-01-01mybatisplus 多表關(guān)聯(lián)條件分頁查詢的實現(xiàn)
本文主要介紹了mybatisplus 多表關(guān)聯(lián)條件分頁查詢的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-01-01