导入依赖
在pom文件中加入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
LogAOP
创建一个日志切面,用来记录方法执行耗时
@Aspect
@Order(1)
@Configuration
public class LogAop {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// 切点
private final static String POINTCUT_LOG_CONTROLLER = "execution (* com.frog.mybatisplus.controller.*.*(..))";
private final static String POINTCUT_LOG_SERVICE = "execution (* com.frog.mybatisplus.service.impl.*.*(..))";
private final static String POINTCUT_LOG = POINTCUT_LOG_CONTROLLER + " || " + POINTCUT_LOG_SERVICE;
// 环绕通知
@Around(POINTCUT_LOG)
public Object logAround(ProceedingJoinPoint joinPoint) {
// 获取切点参数
Object[] args = joinPoint.getArgs();
// 获取方法全限定名
String methodName = joinPoint.getSignature().getDeclaringTypeName();
// 打印执行前日志
printBeforeLog(methodName, args);
// 执行时间起
long start = System.currentTimeMillis();
try {
// 执行方法
Object proceed = joinPoint.proceed();
// 执行时间止
long end = System.currentTimeMillis();
// 打印执行后日志
printAfterLog(methodName, args, proceed, end - start);
return proceed;
} catch (Throwable e) {
// 处理异常
printErrorLog(methodName, args, e);
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
}
private void printErrorLog(String methodName, Object[] args, Throwable e) {
if (logger.isInfoEnabled()) {
logger.info("[{}] 方法执行异常,参数[{}],异常信息[{}]",
methodName,
argsToParamStr(args),
e);
}
}
private void printAfterLog(String methodName, Object[] args, Object proceed, long l) {
if (proceed == null) {
proceed = "null";
}
if (logger.isInfoEnabled()) {
logger.info("[{}] 方法执行成功,参数[{}],执行时间[{}ms],返回值[{}]",
methodName,
argsToParamStr(args),
l,
proceed);
}
}
private void printBeforeLog(String methodName, Object[] args) {
if (logger.isInfoEnabled()) {
logger.info("[{}] 方法请求成功,参数[{}]", methodName, argsToParamStr(args));
}
}
private String argsToParamStr(Object[] args) {
return Stream.of(args)
.map(o -> {
if (o == null) {
return "null";
}
if (o.getClass().isPrimitive()) {
// 基本类型输出值
return o.toString();
} else {
// 不是基本类型
if (o.toString().length() > 100) {
return o.getClass().getName();
} else {
return o.toString();
}
}
})
.collect(Collectors.joining(", ", "{", "}"));
}
}
@Aspect注解表示这是一个切面
@Order(1)执行顺序,数字越小越先进入切面
@Around环绕通知,相当于把执行方法包裹起来,也可以使用@Before+@AfterReturning+@AfterThrowing达到相同效果。