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

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

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

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

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

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

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

1. 導(dǎo)入切面需要的依賴包

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

2. 自定義注解 AOPLog , 指定注解使用在方法上, 指定在運(yùn)行時(shí)有效

Target:描述了注解修飾的對(duì)象范圍

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

Retention: 表示注解保留時(shí)間長(zhǎng)短

  • SOURCE:在源文件中有效,編譯過程中會(huì)被忽略
  • CLASS:隨源文件一起編譯在class文件中,運(yùn)行時(shí)忽略
  • RUNTIME:在運(yùn)行時(shí)有效

只有定義為 RetentionPolicy.RUNTIME(在運(yùn)行時(shí)有效)時(shí),我們才能通過反射獲取到注解,然后根據(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)
// 指定生效至運(yùn)行時(shí)
@Retention(RetentionPolicy.RUNTIME)
public @interface AOPLog {
?
? ? /**
? ? ?* 指定是否詳情顯示
? ? ?* true 顯示詳情, 默認(rèn)false
? ? ?*
? ? ?* @return
? ? ?*/
? ? boolean isDetail() default false;
?
}

3. 設(shè)置切面類

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);
?
? ? /**
? ? ?* 指定切點(diǎn), 切點(diǎn)的位置是存在該注解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("進(jìn)入方法[{}], 參數(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. 編寫測(cè)試接口, 測(cè)試切面日志是否生效

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, 同時(shí)isDetail = true
? ? @AOPLog(isDetail = true)
? ? @GetMapping("/testAOPLogDetail")
? ? public ResponseEntity<?> testAOPLogDetail() {
? ? ? ? return XyResponseEntity.ok();
? ? }
?
}

5. 分別請(qǐng)求兩測(cè)試接口

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

控制臺(tái)打印出

2019-12-26 14:00:56.336  ***.AOPLogAspect    : 進(jìn)入方法[testAOPLog], 參數(shù)有[]
 
2019-12-26 14:01:00.372  ***.AOPLogAspect    : 進(jìn)入方法[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切面攔截成功,打印出了日志,同時(shí)設(shè)置了 isDetail = true 時(shí),打印出了結(jié)束日志。

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

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

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

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

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

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

    Java listener簡(jiǎn)介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

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

    JAVA多線程之中斷機(jī)制及處理中斷的方法

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

    Spring?IOC中的組件掃描

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

    深度解析Java中ArrayList的使用

    ArrayList?類是一個(gè)可以動(dòng)態(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í)行順序是一個(gè)筆試的考點(diǎn),通過這篇文章希望大家能徹底了解它們之間的執(zhí)行順序,需要的朋友可以參考下
    2023-05-05
  • Java使用modbus-master-tcp實(shí)現(xiàn)modbus tcp通訊

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

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

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

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

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

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

最新評(píng)論

莱州市| 昆明市| 饶平县| 安泽县| 咸宁市| 遂平县| 同江市| 沈丘县| 绥滨县| 河间市| 阿拉尔市| 老河口市| 安多县| 四子王旗| 门头沟区| 绥芬河市| 中卫市| 巴南区| 济阳县| 确山县| 崇信县| 滁州市| 海南省| 浦江县| 罗江县| 芒康县| 黑山县| 正安县| 夏津县| 厦门市| 犍为县| 卢龙县| 衡东县| 雅江县| 东乌珠穆沁旗| 乌拉特后旗| 舟曲县| 仁寿县| 云阳县| 华宁县| 黔南|