SpringBoot自定義注解之實現AOP切面日志詳解
更新時間:2022年09月02日 16:20:36 作者:你是我的小丫小太陽
這篇文章主要為大家詳細介紹了SpringBoot自定義注解之實現AOP切面統(tǒng)一打印出入參日志,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
通過自定義注解的方式(如:@SysLog(obj = "操作對象", text = "操作內容"),在 SpringBoot 中來實現 AOP 切面統(tǒng)一打印出入參日志。
一、先看下項目結構

二、Maven JAR依賴
<!-- AOP --> ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-aop</artifactId> </dependency>
三、自定義注解
@SysLog
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
?
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface SysLog {
?
? ? /**
? ? ?* 操作對象
? ? ?* **/
? ? String obj() default "";
?
? ? /**
? ? ?* 操作內容
? ? ?* **/
? ? String text() default "";
}四、AOP切面
import java.lang.reflect.Method;
?
import com.zxk.demo.annotation.SysLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
?
?
@SuppressWarnings("all")
@Aspect
@Component
public class SysLogAspect {
?
? ? // 切入點
? ? @Pointcut(value = "@annotation(com.zxk.demo.annotation.SysLog)")
? ? private void pointcut() {
? ? }
?
? ? /**
? ? ?* 在方法執(zhí)行前
? ? ?* @param point
? ? ?* @param myLog
? ? ?* @return
? ? ?*/
? ? @Before(value = "pointcut() && @annotation(sysLog)")
? ? public void before(SysLog sysLog){
? ? ? ? System.out.println("++++執(zhí)行了before方法++++");
? ? }
?
?
? ? /**
? ? ?* 在方法執(zhí)行前后
? ? ?* @param point
? ? ?* @param myLog
? ? ?* @return
? ? ?*/
? ? @Around(value = "pointcut() && @annotation(sysLog)")
? ? public Object around(ProceedingJoinPoint point, SysLog sysLog) {
? ? ? ? System.out.println("++++執(zhí)行了around方法++++");
? ? ? ? String obj = sysLog.obj();
? ? ? ? String text = sysLog.text();
? ? ? ? // 攔截的類名
? ? ? ? Class clazz = point.getTarget().getClass();
? ? ? ? // 攔截的方法
? ? ? ? Signature sig = point.getSignature();
? ? ? ? MethodSignature msig = null;
? ? ? ? if (!(sig instanceof MethodSignature)) {
? ? ? ? ? ? throw new IllegalArgumentException("該注解只能用于方法");
? ? ? ? }
? ? ? ? msig = (MethodSignature) sig;
? ? ? ? Object target = point.getTarget();
? ? ? ? Method currentMethod;
? ? ? ? try {
? ? ? ? ? ? currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
? ? ? ? ? ? System.out.println("執(zhí)行了類:" + clazz.getSimpleName());
? ? ? ? ? ? System.out.println("方法:" + currentMethod.getName());
? ? ? ? ? ? System.out.println("自定義注解:" + obj+"==="+text);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? try {
? ? ? ? ? ? return point.proceed(); // 執(zhí)行程序
? ? ? ? } catch (Throwable throwable) {
? ? ? ? ? ? throwable.printStackTrace();
? ? ? ? ? ? return throwable.getMessage();
? ? ? ? }
? ? }
?
? ? /**
? ? ?* 方法執(zhí)行后
? ? ?* @param joinPoint
? ? ?* @param myLog
? ? ?* @param result
? ? ?* @return
? ? ?*/
? ? @AfterReturning(value = "pointcut() && @annotation(sysLog)", returning = "result")
? ? public Object afterReturning(JoinPoint joinPoint, SysLog sysLog, Object result) {
? ? ? ? // HttpServletRequest request = ((ServletRequestAttributes)
? ? ? ? // RequestContextHolder.getRequestAttributes()).getRequest();
? ? ? ? // HttpSession session = request.getSession();
? ? ? ? /**
? ? ? ? ?* 將信息保存到數據庫
? ? ? ? ?* **/
? ? ? ? System.out.println("++++執(zhí)行了afterReturning方法++++");
? ? ? ? System.out.println("自定義注解:" + sysLog.obj()+"=="+sysLog.text());
? ? ? ? System.out.println("執(zhí)行結果:" + result);
? ? ? ? return result;
? ? }
?
? ? /**
? ? ?* 方法執(zhí)行后 并拋出異常
? ? ?* @param joinPoint
? ? ?* @param myLog
? ? ?* @param ex
? ? ?*/
? ? @AfterThrowing(value = "pointcut() && @annotation(sysLog)", throwing = "ex")
? ? public void afterThrowing(JoinPoint joinPoint, SysLog sysLog, Exception ex) {
? ? ? ? System.out.println("++++執(zhí)行了afterThrowing方法++++");
? ? ? ? System.out.println("請求:" + sysLog.text() + " 出現異常");
? ? }
}五、Controller層實現
@SysLog(obj = "操作對象", text = "操作內容")
@GetMapping("/index")
? ? public String hello() {
// ? ? ? ?int num = 5/0;
// ? ? ? ?System.out.println("執(zhí)行結果:" + num);
? ? ? ? return "hello word";
? ? }六、測試

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Java中創(chuàng)建線程池的幾種方式以及區(qū)別
創(chuàng)建線程池有多種方式,主要通過 Java 的 java.util.concurrent 包提供的 Executors 工具類來實現,本文給大家介紹了幾種常見的線程池類型及其區(qū)別,并通過代碼示例講解的非常詳細,需要的朋友可以參考下2024-11-11
Spark SerializedLambda錯誤的兩種解決方案
這篇文章主要介紹了Spark SerializedLambda錯誤的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
java多線程編程之使用thread類創(chuàng)建線程
在Java中創(chuàng)建線程有兩種方法:使用Thread類和使用Runnable接口。在使用Runnable接口時需要建立一個Thread實例2014-01-01
idea使用war以及war exploded的區(qū)別說明
本文詳細解析了war與warexploded兩種部署方式的差異及步驟,war方式是先打包成war包,再部署到服務器上;warexploded方式是直接把文件夾、class文件等移到Tomcat上部署,支持熱部署,開發(fā)時常用,文章分別列出了warexploded模式和war包形式的具體操作步驟2024-10-10
獲取JPEGImageEncoder和JPEGCode這兩個類的方法
下面小編就為大家?guī)硪黄@取JPEGImageEncoder和JPEGCode這兩個類的方法。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07

