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