javassist获得方法参数名称

举例,方法get(String name, long id),目的想获得name,id这两个名称:

初衷:做日志拦截的时候,比如拦截了方法get(String name, long id),想在日志表中记录成姓名:admin,主键:123,

就需要获取方法的参数名称,以便将参数名称翻译成对应的中文名,比如name对应姓名,id对应主键

package cn.sniper.reflect.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import com.audaque.webkit.web.action.IndexAction;
public class ReflectUtil {
 
 private static final Map<String, List<String>> PARAM_MAP = new HashMap<String, List<String>>();
 
 private static final ReadWriteLock RWL = new ReentrantReadWriteLock();
 
 private static final ClassPool CLASS_POOL = ClassPool.getDefault();  
 
 static {
  //解决javassist.NotFoundException报错
  CLASS_POOL.insertClassPath(new ClassClassPath(IndexAction.class));
 }
 /**
  * 拿到方法的参数名称
  * 比如get(long id, String name)
  * 获得id, name
  */
 public static List<String> getParamNameList(Class clazz, String methodName) {
  RWL.readLock().lock();
  List<String> paramNameList = PARAM_MAP.get(clazz.getName()+"-"+methodName);
  try {
   if(paramNameList == null || paramNameList.size() <= 0) {
    try {
     RWL.readLock().unlock();
     RWL.writeLock().lock();
     if(paramNameList == null || paramNameList.size() <= 0) {
      try {  
       paramNameList = new ArrayList<String>();
          CtClass cc = CLASS_POOL.get(clazz.getName());  
          CtMethod cm = cc.getDeclaredMethod(methodName);  
       
          // 使用javaassist的反射方法获取方法的参数名  
          MethodInfo methodInfo = cm.getMethodInfo();  
          CodeAttribute codeAttribute = methodInfo.getCodeAttribute();  
          LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);  
          if (attr != null) {  
           int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;  
           for (int i = 0; i < cm.getParameterTypes().length; i++) {
               paramNameList.add(attr.variableName(i + pos));
           }
          }  
      } catch (NotFoundException e) {  
          e.printStackTrace();  
      }  
      
      PARAM_MAP.put(clazz.getName()+"-"+methodName, paramNameList);
     }
    } finally {
     RWL.writeLock().unlock();
     RWL.readLock().lock();
    }
   }
   
  } finally {
   RWL.readLock().unlock();
  }
  
  return paramNameList;
 }
 
}
时间: 2024-11-08 20:57:15

javassist获得方法参数名称的相关文章

J2SE_通过反射能获取方法参数名称吗?

一.Java通过反射可以获取方法的参数名称吗? 不能!!! 二.测试示例代码: import java.lang.reflect.Method; class T { public void print(String username) { System.out.println(username); } } public class Test { public static void main(String[] args) { T t = new T(); t.print("zhangsan&qu

用ASM吧,获取方法参数名称!参见SPRING源代码LocalVariableTableParameterNameDiscoverer

/** * Inspects the target class. Exceptions will be logged and a maker map returned * to indicate the lack of debug information. */ private Map<Member, String[]> inspectClass(Class<?> clazz) { InputStream is = clazz.getResourceAsStream(ClassUt

为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】

每篇一句 胡适:多谈些问题,少聊些主义 前言 Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用.如果你往深了一步去思考,你应该会有这样的疑问: 在使用Spring MVC的时候,你即使不使用注解,只要参数名和请求参数的key对应上了,就能自动完成数值的封装 在使用MyBatis(接口模式)时,接口方法向xml里的SQL语句传参时,必须(当然不是100%的必须,特殊情况此处不做考虑)使用@Param('')指定key值,在SQL中才可以取到 我敢相信这绝不是我一

运行时在方法内部获取该方法的名称及参数相关信息

package com.dongjak.scripts.java.反射; import java.lang.reflect.Method; import net.sf.json.JSONObject; import com.dongjak.annotations.LogTarget; /** * * @author dongjak * * */ public class 运行时在方法内部获取该方法的名称及参数相关信息 { public static void main(String[] args

Spring AOP获取拦截方法的参数名称跟参数值

Spring AOP获取拦截方法的参数名称跟参数值 注意:这种方式需要JDK1.8版本支持 开始: 1.aop配置: <aop:aspectj-autoproxy expose-proxy="true" /> 注意该配置需要配置在spring mvc的配置文件中,因为需要拦截controller层方法 或者在必须要配置在spring配置文件中的情况下,同时需要拦截controller层的方法,可以在spring配置文件中加入controller层的包扫描 2.具体代码: i

Javassist进行方法插桩

javassist官网 http://jboss-javassist.github.io/javassist/ javassist API网 http://jboss-javassist.github.io/javassist/html/index.html javassist参考博客 https://www.ibm.com/developerworks/cn/java/j-dyn0916/  Ⅰ插桩 自动用例生成(使用Randoop) 评价(对用例筛选冗余)>功能覆盖.语句覆盖(一般用后者)

java如何获取方法参数名

在java中,可以通过反射获取到类.字段.方法签名等相关的信息,像方法名.返回值类型.参数类型.泛型类型参数等,但是不能够获取方法的参数名.在实际开发场景中,有时需要根据方法的参数名做一些操作,比如像spring-mvc中,@RequestParam.@PathVariable注解,如果不指定相应的value属性,默认就是使用方法的参数名做为HTTP请求的参数名,它是怎么做到的呢? 在这样情况下,有两种方法获取方法来解决这种需求,第一种方法是使用注解,在注解中指定对应应的参数名称,在需要使用参数

JQuery中$.ajax()方法参数详解

url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 delete也可以使用,但仅部分浏览器支持. timeout: 要求为Number类型的参数,设置请求超时时间(毫秒).此设置将覆盖$.ajaxSetup()方法的全局设 置. async:要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求. 如果需要发送同步请求,请将此选项

c# 方法参数(传值,传引用,ref,out,params,可选参数,命名参数)

 一.方法参数的类型----值类型和引用类型 当方法传递的参数是值类型时,变量的栈数据会完整地复制到目标参数中即实参和形参中的数据相同但存放在内存的不同位置.所以,在目标方法中对形参所做的更改不会对调用者的初始变量产生任何影响. 当方法传递的参数是引用类型是,只是将变量的引用复制到目标参数中,实参和形参的引用指向内存中的同一位置.所以,在目标方法中对形参所做的更改会影响调用者的初始变量. 二.一些特殊的方法参数 1.引用参数---ref (使值类型的变量做方法参数时也可以传引用) 一些数据类型(