import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 切面方式:打印调用类
* created by zj on 18-09-29
*/
@Component
@Aspect
@ComponentScan
@EnableAspectJAutoProxy
public class LogAop {
private Logger logger = LoggerFactory.getLogger(LogAop.class);
/**
* 打印类method的名称以及参数
* @param point 切面
*/
public void printMethodParams(JoinPoint point){
if(point == null){
return;
}
String className = point.getTarget().getClass().getName();
String simpleClassName = point.getTarget().getClass().getSimpleName();
String methodName = point.getSignature().getName();
// 获取方法的参数值数组。
Object[] method_args = point.getArgs();
try {
// 获取方法参数名称
String[] paramNames = getFieldsName(className, methodName);
// 打印
logParam(paramNames, method_args, className, methodName, simpleClassName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 使用javassist来获取方法参数名称
* @param className 类名
* @param methodName 方法名
* @return
* @throws Exception
*/
private String[] getFieldsName(String className, String methodName) throws Exception {
Class<?> clazz = Class.forName(className);
String clazz_name = clazz.getName();
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(clazz);
pool.insertClassPath(classPath);
CtClass ctClass = pool.get(clazz_name);
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;
}
/**
* 判断是否为基本类型:包括String
* @param clazz clazz
* @return true:是; false:不是
*/
private boolean isPrimite(Class<?> clazz){
if (clazz.isPrimitive() || clazz == String.class){
return true;
}else {
return false;
}
}
/**
* 日志输出
* @param paramsArgsName
* @param paramsArgsValue
* @param className
* @param methodName
* @param simpleClassName
*/
private void logParam(String[] paramsArgsName, Object[] paramsArgsValue, String className, String methodName, String simpleClassName){
if(ArrayUtils.isEmpty(paramsArgsName) || ArrayUtils.isEmpty(paramsArgsValue)){
logger.info("该方法没有参数");
return;
}
StringBuilder sb = new StringBuilder("\nSpringBoot controller report -------- ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append(" ----------------------\n");
sb.append("Controller : ").append(className).append(".(").append(simpleClassName).append(".java:1)");
sb.append("\nMethod : ").append(methodName).append("\n");
for (int i=0;i<paramsArgsName.length;i++){
//参数名
String name = paramsArgsName[i];
//参数值
Object value = paramsArgsValue[i];
sb.append(name +" = ");
if(isPrimite(value.getClass())){
sb.append(value + " \n");
}else {
sb.append(value.toString() + " \n");
}
}
sb.append("--------------------------------------------------------------------------------\n");
logger.info(sb.toString());
}
@Before("execution(public * com.demo.test..controller..*(..))")
public void before(JoinPoint point) {
this.printMethodParams(point);
}
}
以上代码需修改下注解里需要切入controller
@Before("execution(public * com.demo.test..controller..*(..))")
效果:
注:若方法传入的参数为vo, 要打印出参数值,需添加toString方法