aop springboot 传入参数_springboot aop获得方法参数

因项目需要,要求在方法执行前后打印参数及返回值,上网找了一个可用的,利用aop做的工具,稍作修改后,把入参,出参放到一个json里,成果跟大家分享一下。

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import javassist.*;

import javassist.bytecode.CodeAttribute;

import javassist.bytecode.LocalVariableAttribute;

import javassist.bytecode.MethodInfo;

import org.apache.commons.lang.StringUtils;

import org.apache.commons.lang3.ArrayUtils;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import org.springframework.stereotype.Component;

import java.util.Date;

/**

* Created with IntelliJ IDEA.

* Description:

* User: spc

* Date: 2018-04-18

* Time: 10:55

*/

@Component //声明组件

@Aspect //声明切面

@ComponentScan //组件自动扫描

@EnableAspectJAutoProxy //spring自动切换JDK动态代理和CGLIB

public class LogRecordAspect {

private Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);

/**

* 打印类method的名称以及参数

* @param point 切面

*/

public JSONObject printMethodParams(JoinPoint point,String temp){

if(point == null){

return new JSONObject();

}

/**

* Signature 包含了方法名、申明类型以及地址等信息

*/

String class_name = point.getTarget().getClass().getName();

String method_name = point.getSignature().getName();

//重新定义日志

logger = LoggerFactory.getLogger(point.getTarget().getClass());

logger.info("class_name = {},temp:"+temp,class_name);

logger.info("method_name = {},temp:"+temp,method_name);

JSONObject paramJson = new JSONObject();

paramJson.put("class_name",class_name);

paramJson.put("method_name",method_name);

paramJson.put("temp",temp);

/**

* 获取方法的参数值数组。

*/

Object[] method_args = point.getArgs();

try {

//获取方法参数名称

String[] paramNames = getFieldsName(class_name, method_name);

//打印方法的参数名和参数值

String param_name = logParam(paramNames,method_args);

paramJson.put("param_name",JSONObject.parse(param_name));

} catch (Exception e) {

e.printStackTrace();

}

return paramJson;

}

/**

* 使用javassist来获取方法参数名称

* @param class_name 类名

* @param method_name 方法名

* @return

* @throws Exception

*/

private String[] getFieldsName(String class_name, String method_name) throws Exception {

Class> clazz = Class.forName(class_name);

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(method_name);

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

// 如果是静态方法,则第一就是参数

// 如果不是静态方法,则第一个是"this",然后才是方法的参数

// 我接口中没有写public修饰词,导致我的数组少一位参数,所以再往后一位,原本应该是 XX ? 0 : 1

int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 1 : 2;

for (int i=0;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;

}

}

/**

* 打印方法参数值 基本类型直接打印,非基本类型需要重写toString方法

* @param paramsArgsName 方法参数名数组

* @param paramsArgsValue 方法参数值数组

*/

private String logParam(String[] paramsArgsName,Object[] paramsArgsValue){

StringBuffer buffer = new StringBuffer();

if(ArrayUtils.isEmpty(paramsArgsName) || ArrayUtils.isEmpty(paramsArgsValue)){

buffer.append("该方法没有参数");

return buffer.toString();

}

for (int i=0;i

//参数名

String name = paramsArgsName[i];

//参数值

Object value = paramsArgsValue[i];

buffer.append("\""+name+"\":");

if(isPrimite(value.getClass())){

buffer.append("\""+value+"\",");

}else {

buffer.append(JSON.toJSONString(value)+",");

}

}

return "{"+buffer.toString().substring(0,buffer.toString().length()-1)+"}";

}

/**

*

Before : 在方法执行前进行切面

*

execution : 定义切面表达式

*

public * com.eparty.ccp.*.impl..*.*(..)

*

public :匹配所有目标类的public方法,不写则匹配所有访问权限

*

第一个* :方法返回值类型,*代表所有类型

*

第二个* :包路径的通配符

*

第三个..* :表示impl这个目录下所有的类,包括子目录的类

*

第四个*(..) : *表示所有任意方法名,..表示任意参数

*

* @param

*/

/*@Before("execution(* com.abc.service.*.many*(..))")

public void before(JoinPoint point) {

this.printMethodParams(point);

}*/

@Around("execution(* com.abc.service.*.many*(..))")

public Object around(ProceedingJoinPoint pj) throws Throwable {

Long temp = System.currentTimeMillis();

JSONObject paramJson = this.printMethodParams(pj,String.valueOf(temp));

logger.info("请求前:"+paramJson.toString());

Object retVal = pj.proceed();

JSONObject returnJson = new JSONObject();

returnJson.put("temp",temp);

returnJson.put("class_name",paramJson.get("class_name"));

returnJson.put("method_name",paramJson.get("method_name"));

returnJson.put("return_name",retVal);

logger.info("请求后:"+returnJson.toString());

return retVal;

}

}

备注:

1.ProceedingJoinPoint是JoinPoint的子类。

2.around方法应该有返回值,拿了没放回去后果就是丢失返回值....

public Object around(……){

……

return retVal;

}

你可能感兴趣的:(aop,springboot,传入参数)