简介
在前段时间,看自己写的代码的时候,发现存在大量繁琐的日志记录,影响观感不说,后期的维护上也是十分麻烦,决定通过AOP去解决这个问题,先做记录。
与SpringBoot框架的整合所需要的依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
通过查阅网上资料,了解到通过AOP记录日志,存在两种方式
- 基于注解
- 基于表达式
详细说明
一、基于注解的AOP日志
在使用注解这种方式前,我们需要自定义一个属于自己的注解
@VoiceLog
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface VoiceLog {
}
-
@@Target
说明该注解的使用范围,包含10个枚举值; -
@Retention
说明编译程序如何对待自定义的Annotation,包含三个枚举值:SOURCE
,CLASS
,RUNTIME
;
完成之后,继续下面的步骤
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Aspect // 声明这是一个切面类
@Component // 注册为一个bean
@Slf4j // lombok日志注解
public class AspectLog {
/**
* 对存在注解 `VoiceLog`的方法做日志记录
*
* @param joinPoint joinPoint
* @param voiceLog voiceLog
* @throws Throwable Throwable
* @see VoiceLog
*/
@Around(value = "@annotation(voiceLog)") // aspect增强注解,对存在该注解方法的前后做拦截
public Object logAroud(ProceedingJoinPoint joinPoint, VoiceLog voiceLog) throws Throwable {
// 获取当前毫秒
long beginTime = System.currentTimeMillis();
// 执行方法体
Object result = joinPoint.proceed();
// 计算方法执行时间
long time = System.currentTimeMillis() - beginTime;
//获取当前方法的类名
String className = joinPoint.getTarget().getClass().getSimpleName();
// 获取切点处的签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// 获取当前的方法名
String methodName = methodSignature.getMethod().getName();
// 获取参数名称
String[] paramNames = methodSignature.getParameterNames();
// 获取参数值
Object[] params = joinPoint.getArgs();
// 把参数名称和参数值组装成json格式
JSONObject paramsJson = new JSONObject(paramNames.length);
for (int i = 0; i < paramNames.length; i++) {
paramsJson.put(paramNames[i], params[i]);
}
// 日志输出
log.info("TargetClass:{}; method:{}; requestParams:{}; response:{}; time:{}ms", className, methodName, paramsJson.toJSONString(), result, time);
return Object;
}
}
配置文件添加配置
spring.aop.proxy-target-class=true