利用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; } }