说明: 该日志切面,仅仅提供简单的方法入参、出参和方法耗时等简易记录,可自行定制!
1. 引入依赖
<!-- aop相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<!-- gson相关依赖(把java对象转化为json类型字符串)-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
2. 编写LogAspect切面类
package com.ssm.log;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
@ConditionalOnProperty(name = {"log.aspect.enable"}, havingValue = "true", matchIfMissing = true)
public class LogAspect {
//统一日志管理 在Controller service 和 微服务rpc调用的链路过程中打印参数等信息
/*
1/所有返回类型 public private等
2.包名 com.ssm.*.controller
3.类名 *Controller
4.方法名(不限参数) *(..)
* */
@Pointcut("execution(* com.ssm.*.controller.*Controller.*(..)) || execution(* com.ssm.*.service.*Service.*(..))")
private void pointCut(){} //切点
//使用环绕通知方式(before在方法前执行 after在方法后执行,around可自定义方法执行前后的操作,通过proceed执行切面方法)
@Around("pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object[] reqArgs = point.getArgs(); //获取参数列表
String req = new Gson().toJson(reqArgs); //Gson.toJson把java对象转化为json字符串
//获取类名 + 方法名(强转为MethodSignature)
MethodSignature signature = (MethodSignature) point.getSignature();
String methodNames = signature.getDeclaringType().getName() + "." + signature.getName();
//打印入参的 类名.方法名 和 参数req
log.info("{},req:{}", methodNames, req);
long start = System.currentTimeMillis(); //获取方法执行前时间
Object responseObj = point.proceed(); //执行切面类方法
String resp= new Gson().toJson(responseObj); //获取响应的json结果
long end = System.currentTimeMillis(); //获取方法执行后时间
//打印响应结果 和 执行时间
log.info("{},response:{},costTime:{}", methodNames, req, end - start);
//环绕通知 需要返回目标方法执行后的结果即point.proceed()的返回值,否则会出现空指针(获取完数据被日志切面截胡)
return responseObj;
}
}