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

package com.xxx.aspect;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * service 日志打印
 *
 * @author JZDELD
 * @date 2021/11/4 10:25
 */
@Slf4j
@Aspect
@Component
public class ServiceLogAspect {
    /**
     * Pointcut解释
     * (bean(*ServiceImpl) || bean(*Service))
     * 所有以 ServiceImpl、Service 结尾的 bean
     * <p>
     * !(execution(public * com.xxx.activity..*.syn*(..)) || execution(public * com.xxx.activity..*.past*(..)))
     * 不选中 com.xxx.activity 包以及子包下 syn或past开头的public方法
     * <p>
     * (within(com.xxx.activity.coupon..*) || within(com.xxx.activity.member..*) || within(com.xxx.activity.integral..*))
     * 选中com.xxx.activity 下的 coupon、member、integral 包以及子包
     */
    @Pointcut("(bean(*ServiceImpl) || bean(*Service)) && " +
            "!(execution(public * com.xxx.activity..*.syn*(..)) || execution(public * com.xxx.activity..*.past*(..))) && " +
            "(within(com.xxx.activity.coupon..*) || within(com.xxx.activity.member..*) || within(com.xxx.activity.integral..*))")
    public void pointCut() {
    }

    /**
     * 前置
     * 打印类路径和参数
     *
     * @param joinPoint
     */
    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        try {
            // 当前切入的类
            Class<?> clazz = joinPoint.getTarget().getClass();
            // 当前执行的方法所属的类、包
            String className = clazz.getName();

            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 当前执行的方法名称
            String methodName = signature.getName();

            // 参数名
            String[] fieldsName = getFieldsName(clazz, methodName);
            // 入参
            String param = getParam(fieldsName, joinPoint.getArgs());

            log.warn("\n{}\n{}() <= {}", className, methodName, param);
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }
    }

    /**
     * 获取入参并转成json
     *
     * @param fieldsName  参数名
     * @param fieldsValue 参数值
     * @return
     */
    private String getParam(String[] fieldsName, Object[] fieldsValue) {
        if (ArrayUtil.isEmpty(fieldsName)) {
            return "";
        }

        Map<String, Object> result = new LinkedHashMap<>(fieldsName.length);
        for (int i = 0; i < fieldsName.length; i++) {
            result.put(fieldsName[i], JSON.toJSONString(fieldsValue[i]));
        }

        return JSON.toJSONString(result);
    }

    /**
     * 获取参数名
     *
     * @param clazz
     * @param methodName
     * @return
     * @throws Exception
     */
    private String[] getFieldsName(Class<?> clazz, String methodName) throws Exception {
        String clazzName = clazz.getName();
        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(clazz);
        pool.insertClassPath(classPath);

        CtClass ctClass = pool.get(clazzName);
        CtMethod ctMethod = ctClass.getDeclaredMethod(methodName);
        MethodInfo methodInfo = ctMethod.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if (attr == null) {
            return null;
        }
        String[] paramsArgsName = new String[ctMethod.getParameterTypes().length];
        int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
        for (int i = 0; i < paramsArgsName.length; i++) {
            paramsArgsName[i] = attr.variableName(i + pos);
        }
        return paramsArgsName;
    }
}

 

posted @ 2021-11-13 11:17  JZDELD  阅读(233)  评论(0编辑  收藏  举报