天天看點

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;

@Component //聲明元件

@Aspect //聲明切面

@ComponentScan //元件自動掃描

@EnableAspectJAutoProxy //spring自動切換JDK動态代理和CGLIB

public class LogRecordAspect {

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

public JSONObject printMethodParams(JoinPoint point,String temp){

if(point == null){

return new JSONObject();

}

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;

}

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;

}

private boolean isPrimite(Class> clazz){

if (clazz.isPrimitive() || clazz == String.class){

return true;

}else {

return false;

}

}

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)+"}";

}

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

}