java使用注解加ASPECT实现拦截方法打印方法日志 admin 2023-09-08 14:39:01 篇首语:本文由小编为大家整理,主要介绍了java使用注解加ASPECT实现拦截方法打印方法日志相关的知识,希望对你有一定的参考价值。 为了熟悉AOP中的ASPECTJ的使用,为了方便我们在写数据搬运型代码时候观测的方便,自己学习并定义了一组切面方法和注解,来实现这个功能,啥都不说了,先上代码: 首先是注解定义: import java.lang.annotation.*;/** * @author wangxiao * @date 2020-05-26 10:38 */@Retention(RetentionPolicy.RUNTIME)@Target( ElementType.METHOD )@Documentedpublic @interface ServiceAroundLog /** * 定义方法名称 * @return */ String methodName() default ""; /** * 是否打印方法执行时间 * @return */ boolean isTimeInterval() default true; /** * 是否打印方法参数 * @return */ boolean isPrintParam() default true; 注解定义完成之后,我们开始定义使用这个注解的切面方法: import com.alibaba.fastjson.JSON;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.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.util.ArrayList;import java.util.List;/** * @author wangxiao * @date 2020-05-26 10:50 */@Aspect@Order(2)@Componentpublic class ServiceAroundLogAspect @Around("@annotation(ServiceAroundLog)") public Object beforeReturnValue(ProceedingJoinPoint point) throws Throwable Method methodSignart = ((MethodSignature) point.getSignature()).getMethod(); ServiceAroundLog methodAnnotation = methodSignart.getAnnotation(ServiceAroundLog.class); if (methodAnnotation != null) Logger logger = LoggerFactory.getLogger(point.getThis().getClass()); boolean isTimeInterval = methodAnnotation.isTimeInterval(); String name = methodAnnotation.methodName(); if (StringUtils.isEmpty(name)) name = methodSignart.getName(); logger.info("----------方法开始执行----------", name); long s = 0; if (isTimeInterval) s = System.currentTimeMillis(); boolean isPrintParam = methodAnnotation.isPrintParam(); if (isPrintParam) Parameter[] parameters = methodSignart.getParameters(); Object[] args = point.getArgs(); if (parameters != null || parameters.length > 0) StringBuilder sb = new StringBuilder(); sb.append("方法参数列表:["); for (int i = 0; i < parameters.length; i++) sb.append("参数名:"); sb.append(parameters[i].getName()); sb.append("-"); sb.append("值:"); sb.append(parameters[i] == null ? "null" : JSON.toJSONString(args[i])); sb.append(""); sb.append("]"); logger.info(sb.toString()); Object proceed = point.proceed(); // 返回值为list类型,打印返回值list数量 if (proceed instanceof ArrayList) final List list = (List) proceed; logger.info("-----返回值为list集合,大小为:-----", list.size()); if (isTimeInterval) logger.info("--------方法执行耗时:ms--------", name, (System.currentTimeMillis() - s)); logger.info("----------方法执行结束----------", name); return proceed; return point.proceed(); 这样当我们在要使用的方法上打上@ServiceAroundLog注解的时候,他就会在方法执行的时候,打印方法执行的日志了。 例如我们是如上图这样使用的。 关于这个AOP的写法,我也要说一下: 切面的编写有三种:before,around,after这三种位置,在before和after我们都会get到我们的joinpoint,获得方法的一些信息,我们可以再方法执行前,方法执行全局和方法执行后做这些事情,之所以我们选择的是around这个切面层进行日志的输出,主要的是有两点: 1、around方法既可以获得到方法执行前的参数,又可以获得方法执行后的return值。 2、before和after,一个在执行前,一个在执行后,根本不能测量方法的执行时间,所以只能放在around中。 另外我在这个过程中学习到的东西有: 1、spring自带了反射的util,是ReflectionUtils还有代理的util是ProxyUtils,并且如果直接通过反射是拿不到具体的值的,只能通过代理。 2、before,around,after的一些作用和AOP具体能够做到什么的一个认识(使用before可以加全局拦截入口认证,使用around可以拦截方法执行过程并且添加额外的东西,使用after可以定义统一关闭或者还原操作等等)。 3、真实的AOP的切入点有五种,分别是Before,Around,After,AfterReturning,AfterThrowing,不同情况下会使用到不同的地方,如下图: 上面的切面,只是我用来学习用的小程序,如果里面存在什么问题,欢迎大家予以指正,同时大家也不要轻易用在生产环境的项目里面,用之前要三思。以上是关于java使用注解加ASPECT实现拦截方法打印方法日志的主要内容,如果未能解决你的问题,请参考以下文章 如何在Mac下编写并运行C++程序 Android NDK- ndk-stack 还原堆栈信息 您可能还会对下面的文章感兴趣: 相关文章 浏览器打不开网址提示“ERR_CONNECTION_TIMED_OUT”错误代码的解决方法 如何安装ocx控件 VMware的虚拟机为啥ip地址老是自动变化 vbyone和EDP区别 linux/debian到底怎么重启和关机 苹果平板键盘被弄到上方去了,如何调回正常? 机器学习常用距离度量 如何查看kindle型号