aop + annotation 实现统一日志记录
在开发中,我们可能需要记录异常日志。由于异常比较分散,每个 service 方法都可能发生异常,如果我们都去做处理,会出现很多重复编码,也不好维护。这种场景就应该想到 aop, aop 的出现就是为了解决这类问题。
我们可以自定义一个注解,在需要记录的日志的方法上面打这个注解。 然后使用 aop ,去切 service 层的方法,判断方法上有没有这个注解,如果有就进行日志处理。
定义注解:
package com.jerryl.auth.service.aop.log;
import java.lang.annotation.*;
/**
\* created by Demon, on 2018/7/22
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RecordLog {
String comment() default "";
}
使用 aspect 做切面
package com.jerryl.auth.service.aop.log;
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.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import java.lang.reflect.Method;
/**
\* created by Demon, on 2018/7/22
*/
@Aspect
@Component
public class RecordLogAspect {
@Pointcut("execution(public * com.jerryl.auth.service..\*Manager.\*(..))")
public void addLog() {}
@Around("addLog()")
public Object addLog(ProceedingJoinPoint joinPoint) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 取类全名
String typeName = joinPoint.getSignature().getDeclaringTypeName();
// 取方法名
String methodName = joinPoint.getSignature().getName();
// 判断方法是不是有日志注解
MethodSignature joinPointObject = (MethodSignature) joinPoint.getSignature();
Method method = joinPointObject.getMethod();
boolean hasRecordLogAnnotation = method.isAnnotationPresent(RecordLog.class);
Object result = null;
try {
if (hasRecordLogAnnotation) {
result = joinPoint.proceed();
stopWatch.stop();
// 方法执行时间
long totalTimes = stopWatch.getTotalTimeMillis();
}
} catch (Throwable throwable) {
// 保存方法名,执行时间,异常信息到数据库表,记录 error 日志,方法返回
}
// 记录操作成功的正常日志
return result;
}
}
如果系统某些操作只有超级管理员的需求,也可以通过 注解加前置通知的方法解决!