定义一个日志注解,指定为方法上使用,生命周期为运行期保留(进入jvm中也生效)
/**
* AOP 日志记录,自定义注解类
*
* @author D30100_chenlong
* @date 2023/2/13 11:41
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GicLog {
/**
* 日志描述,对于什么表格进行操作
* @return String
*/
String description() default "";
}
实现具体的类,去对这个注解做环绕通知和前后切面
/**
* 日志切面类,用于在方法两侧插入日志以定位
*
* @author D30100_chenlong
* @date 2023/2/13 14:03
*/
@Aspect
@Component
public class GicLogAspect {
private ThreadLocal<Long> currentTime = new ThreadLocal<>();
private final static Logger logger = LoggerFactory.getLogger(GicLogAspect.class);
/**
* 以自定义 @GicLog 注解为切点
*/
@Pointcut("@annotation(com.hand.hic.gic.annotation.GicLog)")
public void gicLog(){}
/**
* 在切点之前织入
* @param joinPoint 切点
* @throws ClassNotFoundException ClassNotFoundException
*/
@Before("gicLog()")
public void doBefore(JoinPoint joinPoint) throws ClassNotFoundException {
// 获取 @GicLog 注解的描述信息
String methodDescription = getAspectLogDescription(joinPoint);
// 打印请求相关参数
logger.info("================================== Class Method :{}.{} Start =================================", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// 打印描述信息
logger.info("Description :{}", methodDescription);
}
/**
* 在切点之后织入
*/
@After("gicLog()")
public void doAfter(JoinPoint joinPoint){
// 接口结束后换行, 方便分割查看
logger.info("================================== Class Method :{}.{} End =================================", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
}
/**
* 获取切面注解的描述
* @param joinPoint 切点
* @return String
* @throws ClassNotFoundException ClassNotFoundException
*/
private String getAspectLogDescription(JoinPoint joinPoint) throws ClassNotFoundException {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] classes = method.getParameterTypes();
if (classes.length == arguments.length) {
description.append(method.getAnnotation(GicLog.class).description());
break;
}
}
}
return description.toString();
}
@Around("gicLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
currentTime.set(System.currentTimeMillis());
Object result = proceedingJoinPoint.proceed();
// 执行耗时
logger.info("Time-Consuming :{} ms", System.currentTimeMillis() - currentTime.get());
currentTime.remove();
return result;
}
}
具体使用方式:在方法上加注解
参考文档
注解相关字段的解释说明:https://www.cnblogs.com/libinhyq/p/16709305.html
实现注解aop的案例:https://juejin.cn/post/6844903832929976328