通過AOP 實現打印全局日志

      網友投稿 709 2025-04-02

      常用注解

      1、@Before

      修飾一個方法時,該方法將作為Before增強處理

      使用@Before修飾事,需要指定一個value屬性值,該屬性值指定一個切入點表達式(既可以是一個已有的切入點,也可以直接定義切入點表達式),用于指定該增強處理將被織入哪些切入點

      表示在切入點執行前需要進行的操作或者需要執行的方法

      2、@After

      同Before

      表示在切入點執行后,進行哪些操作

      通常用于資源釋放

      3、 @Around

      Around增強處理是功能比較強大的增強處理;

      近似等于Before增強處理和AfterReturning增強處理的總和

      既可以在執行目標方法之前織入增強動作,也可以在執行目標方法之后織入增強動作

      Around增強處理可以改變執行目標方法的參數值,也可以改變執行目標方法之后的返回值

      Around增強處理雖然功能強大,但通常需要在線程安全的環境下使用,所以一般用Before和AfterReturning增強處理能解決的問題,不建議用Around

      如果需要目標方法執行之前和之后共享某種狀態數據,則應該考慮使用Around增強處理;尤其是需要改變目標方法的返回值時,則只能使用Around增強處理了

      @Around增強處理事,需要指定一個value屬性,該屬性指定該增強處理被植入的切入點

      當定義一個Around增強處理方法時,該方法的第一個形參必須是ProceedingJoinPoint類型(至少包含一個形參),在增強處理方法體內,調用ProceedingJoinPoint參數的proceed()方法才會執行目標方法——這就是Around增強處理可以完全控制目標方法的執行時機、如何執行的關鍵;如果程序沒有調用ProceedingJoinPoint參數的proceed()方法,則目標方法不會被執行。

      通過AOP 實現打印全局日志

      調用ProceedingJoinPoint參數的proceed()方法時,還可以傳入一個Object[]對象作為參數,該數組中的值將被傳入目標方法作為執行方法的實參

      代碼實現

      maven依賴

      //打印日志的依賴,lombok里還包含了實體注解data org.projectlombok lombok test //aop依賴 org.aspectj aspectjweaver 1.9.6 //引入lombok的日志依賴 org.projectlombok lombok 1.18.12 com.google.code.gson gson 2.8.6

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      aop

      學習了Springboot的都知道,SpringBoot默認配置了AOP。這也是SpringBoot的好處,很多默認配置都給我們簡化了。

      package com.example.springbootorderrabbitmqproducer.AOP; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /** * @author 康世行 * @Title: * @Package com.example.springbootorderrabbitmqproducer.AOP * @Description: 全局打印日志 * @date 2021-12-09 8:05 */ @Aspect @Component @Slf4j public class Logs { /** 以 controller 包下定義的所有請求為切入點 */ @Pointcut("execution(public * com.example.springbootorderrabbitmqproducer.controller..*.*(..))") public void webLog() {} /** * 在切點之前織入 * @param joinPoint * @throws Throwable */ @Before("webLog()") public void doBefore(JoinPoint joinPoint) { try{ // 開始打印請求日志 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 打印請求相關參數 log.info("========================================== Start =========================================="); // 打印請求 url log.info("URL : {}", request.getRequestURL().toString()); // 打印 Http method log.info("HTTP Method : {}", request.getMethod()); // 打印調用 controller 的全路徑以及執行方法 log.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); // 打印請求的 IP log.info("IP : {}", request.getRemoteAddr()); // 打印請求入參 String args = new Gson().toJson(joinPoint.getArgs()); log.info("Request Args : {}", args); } catch (Exception e) { log.error("日志打印失敗"); } } /** * 在切點之后織入 * @throws Throwable */ @After("webLog()") public void doAfter() throws Throwable { log.info("=========================================== End ==========================================="); // 每個請求之間空一行 log.info(""); } /** * 環繞 * @param proceedingJoinPoint * @return * @throws Throwable */ @Around("webLog()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = proceedingJoinPoint.proceed(); // 打印出參 log.info("Response Args : {}", new Gson().toJson(result)); // 執行耗時 log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime); return result; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      controller

      package com.example.springbootorderrabbitmqproducer.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 康世行 * @Title: * @Package com.example.springbootorderrabbitmqproducer.controller * @Description: 測試日志controller * @date 2021-12-09 8:27 */ @RestController @RequestMapping("/test") public class testController { @GetMapping("/info/{mesg}") public String testLoginfo(@PathVariable("mesg") String mesg){ return mesg; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      實現效果

      方法執行之前

      : ========================================== Start ========================================== 2021-12-09 08:39:34.556 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : URL : http://localhost:8080/test/info/ksh 2021-12-09 08:39:34.556 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : HTTP Method : GET 2021-12-09 08:39:34.557 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : Class Method : com.example.springbootorderrabbitmqproducer.controller.testController.testLoginfo 2021-12-09 08:39:34.558 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : IP : 0:0:0:0:0:0:0:1 2021-12-09 08:39:34.560 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : Request Args : ["ksh"]

      1

      2

      3

      4

      5

      6

      7

      方法執行之后

      2021-12-09 08:39:34.564 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : =========================================== End =========================================== 2021-12-09 08:39:34.564 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs :

      1

      2

      3

      方法執行前后

      2021-12-09 08:39:34.564 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : Response Args : "ksh" 2021-12-09 08:39:34.564 INFO 32148 --- [nio-8080-exec-1] c.e.s.AOP.Logs : Time-Consuming : 9 ms

      1

      2

      3

      思考

      如下代碼

      思考一,

      Object result = proceedingJoinPoint.proceed();方法出現的位置會影響Around的執行嗎?

      思考二,

      Object result = proceedingJoinPoint.proceed(); 方法出現在

      long startTime = System.currentTimeMillis();

      log.info(“進入指定路徑”+proceedingJoinPoint.getTarget()+“controller”);這兩行代碼下面,方法執行前會輸出什么? 先執行Befour還是先執行Around?

      /** * 環繞 * @param proceedingJoinPoint * @return * @throws Throwable */ @Around("webLog()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long startTime = System.currentTimeMillis(); log.info("進入指定路徑"+proceedingJoinPoint.getTarget()+"controller"); Object result = proceedingJoinPoint.proceed(); // 打印出參 log.info("Response Args : {}", new Gson().toJson(result)); // 執行耗時 log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime); log.info("方法執行完畢"); return result; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      揭曉答案

      思考一,

      會影響Around的方法執行,Object result = proceedingJoinPoint.proceed() 如果出現在第一行,那么日志就不會打印進入方法之前的日志。(指的是Around方法不會打印進入方法之前的日志,并不會影響Before方法)

      原因:

      proceedingJoinPoint.proceed() ,proceed() 這個方法是繼續執行目標方法,就是被切點切入的方法??梢允褂眠@個方法控制被切方法的運行時機。

      思考二,

      這個和上面的around代碼相反,會在進入方法之前打印 進入了那個controller的全路徑,從結果上看around的優先級比Before的優先級高(具體的待研究)

      輸出結果:

      歡迎一鍵三連,支持下小編?。。?/p>

      AOP 面向對象編程

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:電腦沒裝或不能裝Origin Excel有哪些功能可以做出酷酷的圖表(沒有安裝系統的電腦)
      下一篇:WPS工作表標簽怎么添加顏色?
      相關文章
      久久亚洲sm情趣捆绑调教| 精品亚洲永久免费精品| 亚洲黄色在线播放| 亚洲妇熟XXXX妇色黄| 亚洲老熟女五十路老熟女bbw| 亚洲一区中文字幕在线观看| 亚洲ⅴ国产v天堂a无码二区| 在线观看国产区亚洲一区成人| 亚洲AV无码一区二区三区电影 | 亚洲国产精品无码AAA片| 亚洲国产成人AV在线播放| 午夜在线a亚洲v天堂网2019| 久久精品国产亚洲AV麻豆不卡| 九月婷婷亚洲综合在线 | 日韩成人精品日本亚洲| 99亚洲精品卡2卡三卡4卡2卡| 亚洲人成图片网站| 亚洲av日韩av无码av| 91嫩草亚洲精品| 亚洲国产中文在线二区三区免| 99ri精品国产亚洲| 亚洲人成网站影音先锋播放| 亚洲AV日韩AV永久无码下载| 亚洲三区在线观看无套内射| 亚洲日本va午夜中文字幕久久| 亚洲成AV人网址| 亚洲午夜成人精品电影在线观看| 亚洲成a人片在线播放| 国产AV日韩A∨亚洲AV电影| 亚洲老熟女五十路老熟女bbw| 亚洲精品久久无码av片俺去也| 亚洲人成色99999在线观看| 亚洲av午夜精品无码专区| 亚洲一区二区三区精品视频| 亚洲精品国产国语| 亚洲一卡2卡3卡4卡5卡6卡 | 亚洲精品视频在线看| 国产成人亚洲影院在线观看| 亚洲AV伊人久久青青草原| 久久精品国产亚洲AV天海翼| 亚洲码欧美码一区二区三区|