欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

java获取方法的参数名,java获取参数,javassist和as

来源: javaer 分享于  点击 39673 次 点评:236

java获取方法的参数名,java获取参数,javassist和as


javassist和asm都是动态创建、修改字节码的类库。个人感觉主要区别是:asm的性能要好一些。javassist的主要优势是学习成本低,可以根据java源代码生成字节码,而不必直接和字节码打交道。(本例不涉及生成字节码的部分)发现javassist貌似不支持泛型。

基于javassist的实现

package org.cc.tx.aop.javassit;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 org.cc.core.CcException;import org.cc.core.common.Exceptions;/** * <p> * <font color="red">依赖javassit</font>的工具类,获取方法的参数名 * </p> *  * @author dixingxing * @date Apr 20, 2012 */public class Classes {    private Classes() {}    /**     *      * <p>     * 获取方法参数名称     * </p>     *      * @param cm     * @return     */    protected static String[] getMethodParamNames(CtMethod cm) {        CtClass cc = cm.getDeclaringClass();        MethodInfo methodInfo = cm.getMethodInfo();        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute                .getAttribute(LocalVariableAttribute.tag);        if (attr == null) {            throw new CcException(cc.getName());        }        String[] paramNames = null;        try {            paramNames = new String[cm.getParameterTypes().length];        } catch (NotFoundException e) {            Exceptions.uncheck(e);        }        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;        for (int i = 0; i < paramNames.length; i++) {            paramNames[i] = attr.variableName(i + pos);        }        return paramNames;    }    /**     * 获取方法参数名称,按给定的参数类型匹配方法     *      * @param clazz     * @param method     * @param paramTypes     * @return     */    public static String[] getMethodParamNames(Class<?> clazz, String method,            Class<?>... paramTypes) {        ClassPool pool = ClassPool.getDefault();        CtClass cc = null;        CtMethod cm = null;        try {            cc = pool.get(clazz.getName());            String[] paramTypeNames = new String[paramTypes.length];            for (int i = 0; i < paramTypes.length; i++)                paramTypeNames[i] = paramTypes[i].getName();            cm = cc.getDeclaredMethod(method, pool.get(paramTypeNames));        } catch (NotFoundException e) {            Exceptions.uncheck(e);        }        return getMethodParamNames(cm);    }    /**     * 获取方法参数名称,匹配同名的某一个方法     *      * @param clazz     * @param method     * @return     * @throws NotFoundException     *             如果类或者方法不存在     * @throws MissingLVException     *             如果最终编译的class文件不包含局部变量表信息     */    public static String[] getMethodParamNames(Class<?> clazz, String method) {        ClassPool pool = ClassPool.getDefault();        CtClass cc;        CtMethod cm = null;        try {            cc = pool.get(clazz.getName());            cm = cc.getDeclaredMethod(method);        } catch (NotFoundException e) {            Exceptions.uncheck(e);        }        return getMethodParamNames(cm);    }}

基于asm的实现

/** * Classes.java 9:22:44 AM Apr 23, 2012 * * Copyright(c) 2000-2012 HC360.COM, All Rights Reserved. */package org.cc.core.common;import java.io.IOException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import org.cc.core.asm.ClassReader;import org.cc.core.asm.ClassVisitor;import org.cc.core.asm.ClassWriter;import org.cc.core.asm.Label;import org.cc.core.asm.MethodVisitor;import org.cc.core.asm.Opcodes;import org.cc.core.asm.Type;/** * <p> * 基于asm的工具类 * </p> *  * @author dixingxing * @date Apr 23, 2012 */public final class Classes {    private Classes() {    }    /**     *      * <p>比较参数类型是否一致</p>     *     * @param types asm的类型({@link Type})     * @param clazzes java 类型({@link Class})     * @return     */    private static boolean sameType(Type[] types, Class<?>[] clazzes) {        // 个数不同        if (types.length != clazzes.length) {            return false;        }        for (int i = 0; i < types.length; i++) {            if(!Type.getType(clazzes[i]).equals(types[i])) {                return false;            }        }        return true;    }    /**     *      * <p>获取方法的参数名</p>     *     * @param m     * @return     */    public static String[] getMethodParamNames(final Method m) {        final String[] paramNames = new String[m.getParameterTypes().length];        final String n = m.getDeclaringClass().getName();        final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);        ClassReader cr = null;        try {            cr = new ClassReader(n);        } catch (IOException e) {            e.printStackTrace();            Exceptions.uncheck(e);        }        cr.accept(new ClassVisitor(Opcodes.ASM4, cw) {            @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 = cv.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;    }    public static void main(String[] args) throws SecurityException,            NoSuchMethodException {        String[] s = getMethodParamNames(Dates.class.getMethod("parse",                String.class,String.class));        System.out.println(Strings.join(s));        s = getMethodParamNames(Dates.class.getMethod("parse",                String.class,String[].class));        System.out.println(Strings.join(s));    }}
相关栏目:

用户点评