最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot使用自定義注解實現(xiàn)aop切面日志

 更新時間:2022年09月02日 15:18:54   作者:原野灬  
這篇文章主要為大家詳細介紹了springboot使用自定義注解實現(xiàn)aop切面日志,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

平時我們在開發(fā)過程中,代碼出現(xiàn)bug時為了更好的在服務器日志中尋找問題根源,會在接口的首尾打印日志,看下參數(shù)和返回值是否有問題。但是手動的logger.info() 去編寫時工作量較大,這時我們可以使用AOP切面,為所有接口的首尾打印日志。

實現(xiàn)AOP切面日志一般有兩種方式:

1、攔截所有接口controller,在首尾打印日志
2、攔截指定注解的接口,為有該注解的接口首尾打印日志

我們嘗試用自定義注解來實現(xiàn)AOP日志的打印,這樣擁有更高的靈活性。廢話不多說,我們開始

1. 導入切面需要的依賴包

<dependency>
? ? ? <groupId>org.springframework.boot</groupId>
? ? ?<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 自定義注解 AOPLog , 指定注解使用在方法上, 指定在運行時有效

Target:描述了注解修飾的對象范圍

  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述方法變量
  • TYPE:用于描述類、接口或enum類型

Retention: 表示注解保留時間長短

  • SOURCE:在源文件中有效,編譯過程中會被忽略
  • CLASS:隨源文件一起編譯在class文件中,運行時忽略
  • RUNTIME:在運行時有效

只有定義為 RetentionPolicy.RUNTIME(在運行時有效)時,我們才能通過反射獲取到注解,然后根據(jù)注解的一系列值,變更不同的操作。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
/**
?* @author buer
?* @date 2019/12/26
?*/
// 指定注解使用在方法上
@Target(ElementType.METHOD)
// 指定生效至運行時
@Retention(RetentionPolicy.RUNTIME)
public @interface AOPLog {
?
? ? /**
? ? ?* 指定是否詳情顯示
? ? ?* true 顯示詳情, 默認false
? ? ?*
? ? ?* @return
? ? ?*/
? ? boolean isDetail() default false;
?
}

3. 設置切面類

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
?
import java.lang.reflect.Method;
?
/**
?* @author buer
?* @date 2019/12/26
?* @description //TODO
?*/
// 指定切面類
@Aspect
// 注入容器
@Component
public class AOPLogAspect {
?
? ? private static Logger log = LoggerFactory.getLogger(AOPLogAspect.class);
?
? ? /**
? ? ?* 指定切點, 切點的位置是存在該注解com.xingyun.xybb.demo.annotation.AOPLog
? ? ?*/
? ? @Pointcut("@annotation(com.xingyun.xybb.demo.annotation.AOPLog)")
? ? public void logPointCut() {
? ? }
?
? ? /**
? ? ?* 環(huán)繞通知, 該處寫具體日志邏輯
? ? ?*
? ? ?* @param joinPoint
? ? ?*/
? ? @Around("logPointCut()")
? ? public void logAround(ProceedingJoinPoint joinPoint) {
? ? ? ? MethodSignature signature = (MethodSignature) joinPoint.getSignature();
? ? ? ? // 獲取方法名稱
? ? ? ? String methodName = signature.getName();
? ? ? ? // 獲取入?yún)?
? ? ? ? Object[] param = joinPoint.getArgs();
? ? ? ? StringBuilder sb = new StringBuilder();
? ? ? ? for (Object o : param) {
? ? ? ? ? ? sb.append(o).append("; ");
? ? ? ? }
? ? ? ? log.info("進入方法[{}], 參數(shù)有[{}]", methodName, sb.toString());
?
? ? ? ? String resp = "";
? ? ? ? try {
? ? ? ? ? ? Object proceed = joinPoint.proceed();
? ? ? ? ? ? resp = JSON.toJSONString(proceed, SerializerFeature.WriteMapNullValue);
? ? ? ? } catch (Throwable throwable) {
? ? ? ? ? ? throwable.printStackTrace();
? ? ? ? }
?
? ? ? ? // 獲取方法上的注解,判斷如果isDetail值為true,則打印結(jié)束日志
? ? ? ? Method method = signature.getMethod();
? ? ? ? AOPLog annotation = method.getAnnotation(AOPLog.class);
? ? ? ? boolean isDetail = annotation.isDetail();
? ? ? ? if (isDetail) {
? ? ? ? ? ? log.info("方法[{}]執(zhí)行結(jié)束, 返回值[{}]", methodName, resp);
? ? ? ? }
? ? }
?
}

4. 編寫測試接口, 測試切面日志是否生效

import com.xingyun.xybb.common.response.XyResponseEntity;
import com.xingyun.xybb.demo.annotation.AOPLog;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
?
/**
?* @author buer
?* @date 2019/12/26
?* @description //TODO
?*/
@RestController
public class TestAOPLogController {
? ??
? ? // 指定注解@AOPLog
? ? @AOPLog
? ? @GetMapping("/testAOP")
? ? public ResponseEntity<?> testAOPLog() {
? ? ? ? return XyResponseEntity.ok();
? ? }
?
? ? // 指定注解@AOPLog, 同時isDetail = true
? ? @AOPLog(isDetail = true)
? ? @GetMapping("/testAOPLogDetail")
? ? public ResponseEntity<?> testAOPLogDetail() {
? ? ? ? return XyResponseEntity.ok();
? ? }
?
}

5. 分別請求兩測試接口

http://localhost:8499/demo/testAOP
http://localhost:8499/demo/testAOPLogDetail

控制臺打印出

2019-12-26 14:00:56.336  ***.AOPLogAspect    : 進入方法[testAOPLog], 參數(shù)有[]
 
2019-12-26 14:01:00.372  ***.AOPLogAspect    : 進入方法[testAOPLogDetail], 參數(shù)有[]
2019-12-26 14:01:00.373  ***.AOPLogAspect    : 方法[testAOPLogDetail]執(zhí)行結(jié)束, 返回值[{"body":{"retCode":200,"retEntity":null,"retMsg":"OK"},"headers":{},"statusCode":"OK","statusCodeValue":200}]

由此可看出,AOP切面攔截成功,打印出了日志,同時設置了 isDetail = true 時,打印出了結(jié)束日志。

自定義注解實現(xiàn)AOP切面打印日志完成。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • java向上轉(zhuǎn)型與向下轉(zhuǎn)型詳解

    java向上轉(zhuǎn)型與向下轉(zhuǎn)型詳解

    這篇文章主要為大家詳細介紹了java向上轉(zhuǎn)型與向下轉(zhuǎn)型,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Java?File類提供的方法與操作

    Java?File類提供的方法與操作

    Java使用File類來表示計算機系統(tǒng)磁盤文件的對象類型。File中提供了大量的方法,可以對文件進行增加、刪除、修改、重命名等常規(guī)操作。File類的對象會存儲文件自身的信息,例如文件在系統(tǒng)中的存儲目錄、文件大小、文件讀寫權限等
    2023-03-03
  • Java listener簡介_動力節(jié)點Java學院整理

    Java listener簡介_動力節(jié)點Java學院整理

    這篇文章主要介紹了Java listener簡介,可以用于統(tǒng)計用戶在線人數(shù)等,有興趣的可以了解一下
    2017-07-07
  • JAVA多線程之中斷機制及處理中斷的方法

    JAVA多線程之中斷機制及處理中斷的方法

    這篇文章主要記錄使用 interrupt() 方法中斷線程,以及如何對InterruptedException進行處理,感覺對InterruptedException異常進行處理是一件謹慎且有技巧的活兒,需要的朋友可以參考下
    2023-02-02
  • Spring?IOC中的組件掃描

    Spring?IOC中的組件掃描

    通過自動掃描,Spring?會自動從掃描指定的包及其子包下的所有類,并根據(jù)類上的特定注解將該類裝配到容器中,而無需在?XML?配置文件或?Java?配置類中逐一聲明每一個?Bean,這篇文章主要介紹了Spring?IOC中的組件掃描,需要的朋友可以參考下
    2022-05-05
  • 深度解析Java中ArrayList的使用

    深度解析Java中ArrayList的使用

    ArrayList?類是一個可以動態(tài)修改的數(shù)組,與普通數(shù)組的區(qū)別就是它是沒有固定大小的限制,我們可以添加或刪除元素。本文將通過示例帶你深度解析Java中ArrayList的使用,需要的可以參考一下
    2022-09-09
  • Java中靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)和普通代碼塊的區(qū)別

    Java中靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)和普通代碼塊的區(qū)別

    在Java中,靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)、普通代碼塊的執(zhí)行順序是一個筆試的考點,通過這篇文章希望大家能徹底了解它們之間的執(zhí)行順序,需要的朋友可以參考下
    2023-05-05
  • Java使用modbus-master-tcp實現(xiàn)modbus tcp通訊

    Java使用modbus-master-tcp實現(xiàn)modbus tcp通訊

    這篇文章主要為大家詳細介紹了另外一種Java語言的modbux tcp通訊方案,那就是modbus-master-tcp,文中的示例代碼講解詳細,需要的可以了解下
    2023-12-12
  • SpringBoot調(diào)用公共模塊的自定義注解失效的解決

    SpringBoot調(diào)用公共模塊的自定義注解失效的解決

    這篇文章主要介紹了SpringBoot調(diào)用公共模塊的自定義注解失效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 詳解netty中常用的xml編碼解碼器

    詳解netty中常用的xml編碼解碼器

    這篇文章主要介紹了netty中常用的xml編碼解碼器,進行frame拆分可以使用XmlFrameDecoder,進行xml文件內(nèi)容的解析則可以使用XmlDecoder,接下來我們會詳細講解兩個decoder實現(xiàn)和使用,感興趣的朋友一起看看吧
    2022-05-05

最新評論

罗平县| 安吉县| 岐山县| 晋江市| 开江县| 河曲县| 宜宾市| 太仆寺旗| 乐都县| 炎陵县| 三都| 伊吾县| 龙州县| 广南县| 平舆县| 南和县| 通州区| 和龙市| 安宁市| 灵武市| 合川市| 文水县| 长沙市| 新野县| 温泉县| 浦江县| 蓬溪县| 九寨沟县| 依安县| 富源县| 葵青区| 平乡县| 古浪县| 昌乐县| 南乐县| 信宜市| 宜良县| 都兰县| 斗六市| 灌南县| 翼城县|