利用AOP,实现log打印方法名和入参

  1 package com.xxx.aspect;
  2 
  3 import cn.hutool.core.util.ArrayUtil;
  4 import com.alibaba.fastjson.JSON;
  5 import javassist.ClassClassPath;
  6 import javassist.ClassPool;
  7 import javassist.CtClass;
  8 import javassist.CtMethod;
  9 import javassist.bytecode.CodeAttribute;
 10 import javassist.bytecode.LocalVariableAttribute;
 11 import javassist.bytecode.MethodInfo;
 12 import lombok.extern.slf4j.Slf4j;
 13 import org.aspectj.lang.JoinPoint;
 14 import org.aspectj.lang.annotation.Aspect;
 15 import org.aspectj.lang.annotation.Before;
 16 import org.aspectj.lang.annotation.Pointcut;
 17 import org.aspectj.lang.reflect.MethodSignature;
 18 import org.springframework.stereotype.Component;
 19 
 20 import java.lang.reflect.Modifier;
 21 import java.util.LinkedHashMap;
 22 import java.util.Map;
 23 
 24 /**
 25  * service 日志打印
 26  *
 27  * @author JZDELD
 28  * @date 2021/11/4 10:25
 29  */
 30 @Slf4j
 31 @Aspect
 32 @Component
 33 public class ServiceLogAspect {
 34     /**
 35      * Pointcut解释
 36      * (bean(*ServiceImpl) || bean(*Service))
 37      * 所有以 ServiceImpl、Service 结尾的 bean
 38      * <p>
 39      * !(execution(public * com.xxx.activity..*.syn*(..)) || execution(public * com.xxx.activity..*.past*(..)))
 40      * 不选中 com.xxx.activity 包以及子包下 syn或past开头的public方法
 41      * <p>
 42      * (within(com.xxx.activity.coupon..*) || within(com.xxx.activity.member..*) || within(com.xxx.activity.integral..*))
 43      * 选中com.xxx.activity 下的 coupon、member、integral 包以及子包
 44      */
 45     @Pointcut("(bean(*ServiceImpl) || bean(*Service)) && " +
 46             "!(execution(public * com.xxx.activity..*.syn*(..)) || execution(public * com.xxx.activity..*.past*(..))) && " +
 47             "(within(com.xxx.activity.coupon..*) || within(com.xxx.activity.member..*) || within(com.xxx.activity.integral..*))")
 48     public void pointCut() {
 49     }
 50 
 51     /**
 52      * 前置
 53      * 打印类路径和参数
 54      *
 55      * @param joinPoint
 56      */
 57     @Before("pointCut()")
 58     public void doBefore(JoinPoint joinPoint) {
 59         try {
 60             // 当前切入的类
 61             Class<?> clazz = joinPoint.getTarget().getClass();
 62             // 当前执行的方法所属的类、包
 63             String className = clazz.getName();
 64 
 65             MethodSignature signature = (MethodSignature) joinPoint.getSignature();
 66             // 当前执行的方法名称
 67             String methodName = signature.getName();
 68 
 69             // 参数名
 70             String[] fieldsName = getFieldsName(clazz, methodName);
 71             // 入参
 72             String param = getParam(fieldsName, joinPoint.getArgs());
 73 
 74             log.warn("\n{}\n{}() <= {}", className, methodName, param);
 75         } catch (Exception e) {
 76             log.error("{}", e.getMessage());
 77         }
 78     }
 79 
 80     /**
 81      * 获取入参并转成json
 82      *
 83      * @param fieldsName  参数名
 84      * @param fieldsValue 参数值
 85      * @return
 86      */
 87     private String getParam(String[] fieldsName, Object[] fieldsValue) {
 88         if (ArrayUtil.isEmpty(fieldsName)) {
 89             return "";
 90         }
 91 
 92         Map<String, Object> result = new LinkedHashMap<>(fieldsName.length);
 93         for (int i = 0; i < fieldsName.length; i++) {
 94             result.put(fieldsName[i], JSON.toJSONString(fieldsValue[i]));
 95         }
 96 
 97         return JSON.toJSONString(result);
 98     }
 99 
100     /**
101      * 获取参数名
102      *
103      * @param clazz
104      * @param methodName
105      * @return
106      * @throws Exception
107      */
108     private String[] getFieldsName(Class<?> clazz, String methodName) throws Exception {
109         String clazzName = clazz.getName();
110         ClassPool pool = ClassPool.getDefault();
111         ClassClassPath classPath = new ClassClassPath(clazz);
112         pool.insertClassPath(classPath);
113 
114         CtClass ctClass = pool.get(clazzName);
115         CtMethod ctMethod = ctClass.getDeclaredMethod(methodName);
116         MethodInfo methodInfo = ctMethod.getMethodInfo();
117         CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
118         LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
119         if (attr == null) {
120             return null;
121         }
122         String[] paramsArgsName = new String[ctMethod.getParameterTypes().length];
123         int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
124         for (int i = 0; i < paramsArgsName.length; i++) {
125             paramsArgsName[i] = attr.variableName(i + pos);
126         }
127         return paramsArgsName;
128     }
129 }

 

上一篇:AOP(底层原理)


下一篇:springboot aop+annotation(注解) 实现部分请求(接口)校验token