获取方法参数名问题

一名普通程序员 2015-06-16 02:52:37
我在用javassist 获取方法参数名,发现有时是错位的:

原方法:


在linux下得到参数名是(对比截图中的方法参数及顺序):
Params Names of method: [e, msg_signature, signature, timestamp, nonce, echostr, response]
此时注入的值(对比截图中的方法参数及顺序):
params of method [checkSignature] : [null, a68b41f1207ea0273b195f5d7afe4fb3f4658c7a, edfee8f9db5fdfb649aad307f9338368059cfd93, 1434435829, 902808603, org.apache.catalina.connector.ResponseFacade@5aac4879, org.apache.catalina.connector.RequestFacade@498fe080]

那个参数e 是哪来的,有时候来叫“this” , 这是为何呢?

因为java8以前jvm没有这个编译能力。网上说这个javassist 要有源码的情况下才行? 还是跟编译环境有关?倒底是如何,我也是不清楚。

关键的javassist处理代码:

/**
* 获取方法参数名
* @param clazz
* @param targetMethodName
* @return
* @author : luyanfeng.
* @date : 2014年9月18日
*/
public static String[] getMethodParamsNames(Class<?> clazz, String targetMethodName) {

try {

//
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(clazz));
CtClass cc = pool.get(clazz.getName());
CtMethod cm = cc.getDeclaredMethod(targetMethodName);

MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
String[] variableNames = new String[cm.getParameterTypes().length];
int staticIndex = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
//FIXME 第一个参数会是this???????????
for (int i = 0; i < variableNames.length; i++) {
variableNames[i] = attr.variableName(i + staticIndex);
if(variableNames[i].equals("this")){
variableNames[i] = attr.variableName(i + (++staticIndex) );
}
}
return variableNames;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}




还有什么方式可以正确的获取方法参数呢? 比如springMVC是如何正确的注入的参数???
...全文
869 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
叶不空 2018-10-19
  • 打赏
  • 举报
回复
楼主可否解答一下asm可以获取参数名的原理,java8之前参数名不是被编译器修改了吗?
  • 打赏
  • 举报
回复
今天上来看到有几个朋友在问解决方案,我的是解决了但不是用的javassist。 最后用了asm。 javassist 这个问题也没去再看,几年前的事了,忘了。


    /**
     * <p>
     * 获取方法的参数名
     * </p>
     *
     * @param m
     * @return
     */
    public static String[] getMethodParamsNames(Method m) {
        try {
            final String[] paramNames = new String[m.getParameterTypes().length];
            Class<?> declaringClass = m.getDeclaringClass();
            String className = declaringClass.getName();
            int lastDotIndex = className.lastIndexOf(".");
            InputStream is = declaringClass.getResourceAsStream(className.substring(lastDotIndex + 1) + ".class");
            ClassReader cr = new ClassReader(is);
            cr.accept(new ClassVisitor(Opcodes.ASM4) {
                @Override
                public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
                    final Type[] args = Type.getArgumentTypes(desc);
                    // 方法名相同并且参数个数相同
                    if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) {
                        return super.visitMethod(access, name, desc, signature, exceptions);
                    }
                    MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions);
                    return new MethodVisitor(Opcodes.ASM4, v) {
                        @Override
                        public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                            int i = index - 1;
                            // 如果是静态方法,则第一就是参数
                            // 如果不是静态方法,则第一个是"this",然后才是方法的参数
                            if (Modifier.isStatic(m.getModifiers())) {
                                i = index;
                            }
                            if (i >= 0 && i < paramNames.length) {
                                paramNames[i] = name;
                            }
                            super.visitLocalVariable(name, desc, signature, start, end, index);
                        }

                    };
                }
            }, 0);
            return paramNames;
        } catch (SecurityException | IOException e) {
            e.printStackTrace();
        }
        return null;

    }


cxw65066165 2016-03-02
  • 打赏
  • 举报
回复
关于 javassit 获取参数名错位的问题,想问下解决了没有 我也碰到这个问题了,想问下解决了么
  • 打赏
  • 举报
回复
引用 1 楼 suciver 的回复:
spring-core中有个ParameterNameDiscoverer就是用来获取参数名的,底层用的是asm解析,但是接口方法的参数名无法得到,即只能是非接口类的方法参数名可以

ParameterNameDiscoverer pnd=new DefaultParameterNameDiscoverer();
String[] parameterNames=pnd.getParameterNames(用反射获取到的方法对象);//返回的就是方法中的参数名列表了
哦,到是听说过这个asm,不知那个我说的那个错误不知道您了解吗。 我本地测试用例试测是没任何问题,但放到服务器上就不行了,出错的问题也不固定,很怪,总是方法的原有参数前会多出一个或多个来例不明的参数叫法还怪,像this,这也能行。。。
suciver 2015-06-17
  • 打赏
  • 举报
回复
引用 2 楼 zax0zax 的回复:
哦,到是听说过这个asm,不知那个我说的那个错误不知道您了解吗。 我本地测试用例试测是没任何问题,但放到服务器上就不行了,出错的问题也不固定,很怪,总是方法的原有参数前会多出一个或多个来例不明的参数叫法还怪,像this,这也能行。。。
你直接用spring提供的那个来获取方法的参数名就可以了,javassist这个解析还要自己解析很麻烦的,而且它也是一样对接口类的方法参数名是无法获取的.看看spring提供的就两句话,而且还不会错,javassist还要那么多而且要判断的
suciver 2015-06-16
  • 打赏
  • 举报
回复
spring-core中有个ParameterNameDiscoverer就是用来获取参数名的,底层用的是asm解析,但是接口方法的参数名无法得到,即只能是非接口类的方法参数名可以

ParameterNameDiscoverer pnd=new DefaultParameterNameDiscoverer();
String[] parameterNames=pnd.getParameterNames(用反射获取到的方法对象);//返回的就是方法中的参数名列表了

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧