All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jquicker.args.LocalVariableTableArgsNameDiscoverer Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
package com.jquicker.args;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.ByteArray;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.MethodParametersAttribute;

import com.jquicker.commons.log.JLogger;
import com.jquicker.exception.LocalVariableTableArgsNameDiscovererException;

/**
 * 编译时加上-parameters参数
 *
 * @author OL
 */
public class LocalVariableTableArgsNameDiscoverer implements ArgsNameDiscoverer {

	@Override
	public String[] getArgsNames(Method method) {
		int count = method.getParameterCount();
		String[] argsNames = new String[count];
		Class clazz = method.getDeclaringClass();
		if(clazz.isInterface()) {
			return this.getInterfaceArgNames(method);
		}
		ClassPool pool = ClassPool.getDefault();
		pool.appendSystemPath();
		pool.appendClassPath(new ClassClassPath(clazz));
		CtClass cc = null;
		try {
			cc = pool.get(clazz.getName());
			CtMethod ctMethod = cc.getDeclaredMethod(method.getName()); // 这里给出需要分析的方法名
			MethodInfo methodInfo = ctMethod.getMethodInfo();
			// 如果没有编译任何debug信息,这里getCodeAttribute获取的值为null
			CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
			if (codeAttribute != null) {
				// 如果没有编译本地变量信息,这里getAttribute获取的值为null
				// 注:本地变量表的顺序不一定是按照代码中变量定义的顺序排列的
				LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute
						.getAttribute(LocalVariableAttribute.tag);
				if (attr != null) {
					Tmp[] tmps = new Tmp[attr.tableLength()];
					for (int i = 0; i < tmps.length; i++) {
						// System.out.print(attr.index(i) + ": " + attr.variableName(i) + " ");
						tmps[i] = new Tmp(attr.index(i), attr.variableName(i));
					}
					Arrays.sort(tmps, new Comparator() {
						@Override
						public int compare(Tmp o1, Tmp o2) {
							return o1.compareTo(o2);
						}
					});
					// System.out.println(ArrayUtils.join(tmps, ","));
					boolean isStatic = Modifier.isStatic(method.getModifiers());
					int pos = isStatic ? 0 : 1;
					for (int i = 0; i < argsNames.length; i++) {
						// 非静态方法 第0个参数默认是this
						// argsNames[i] = attr.variableName(i + pos);
						argsNames[i] = tmps[i + pos].name;
					}
				}
			}
		} catch (NotFoundException e) {
			JLogger.error(e.getMessage(), e);
		} finally {
			if (cc != null) {
				cc.detach();
			}
		}
		return argsNames;
	}

	@Override
	public String[] getArgsNames(Constructor ctor) {
		int count = ctor.getParameterCount();
		String[] argsNames = new String[count];
		Class clazz = ctor.getDeclaringClass();
		ClassPool pool = ClassPool.getDefault();
		pool.appendSystemPath();
		pool.appendClassPath(new ClassClassPath(clazz));
		CtClass cc = null;
		try {
			cc = pool.get(clazz.getName());
			CtMethod ctMethod = cc.getDeclaredMethod(ctor.getName());
			MethodInfo methodInfo = ctMethod.getMethodInfo();
			CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
			if (codeAttribute != null) {
				LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute
						.getAttribute(LocalVariableAttribute.tag);
				if (attr != null) {
					Tmp[] tmps = new Tmp[attr.tableLength()];
					for (int i = 0; i < tmps.length; i++) {
						tmps[i] = new Tmp(attr.index(i), attr.variableName(i));
					}
					Arrays.sort(tmps, new Comparator() {
						@Override
						public int compare(Tmp o1, Tmp o2) {
							return o1.compareTo(o2);
						}
					});
					for (int i = 0; i < argsNames.length; i++) {
						argsNames[i] = tmps[i + 1].name;
					}
				}
			}
		} catch (NotFoundException e) {
			JLogger.error(e.getMessage(), e);
		} finally {
			if (cc != null) {
				cc.detach();
			}
		}
		return argsNames;
	}

	/**
	 * 获取接口方法形参名称
	 * @param method
	 * @return
	 * @author OL
	 */
	private String[] getInterfaceArgNames(Method method) {
		int count = method.getParameterCount();
		String[] argsNames = new String[count];
		ClassPool pool = ClassPool.getDefault();
		CtClass cc = null;
		try {
			cc = pool.get(method.getDeclaringClass().getName());
			CtMethod ctMethod = cc.getDeclaredMethod(method.getName());
			MethodInfo methodInfo = ctMethod.getMethodInfo();
			MethodParametersAttribute methodParameters = (MethodParametersAttribute) methodInfo.getAttribute("MethodParameters");
			if(methodParameters == null){
				throw new LocalVariableTableArgsNameDiscovererException("若由框架自动实现dao接口,请开启-parameters编译");
			}
			for (int i = 0; i < count; i++) {
				argsNames[i] = methodParameters.getConstPool().getUtf8Info(ByteArray.readU16bit(methodParameters.get(), i * 4 + 1));
			}
		} catch (NotFoundException e) {
			JLogger.error(e.getMessage(), e);
		} finally {
			if (cc != null) {
				cc.detach();
			}
		}
		return argsNames;
	}

}

class Tmp {
	public int index;
	public String name;

	public Tmp(int index, String name) {
		this.index = index;
		this.name = name;
	}

	public int compareTo(Tmp tmp) {
		int i = this.index - tmp.index;
		if (i > 0) {
			return 1;
		} else if (i == 0) {
			return 0;
		} else {
			return -1;
		}
	}

	@Override
	public String toString() {
		return "Tmp [index=" + index + ", name=" + name + "]";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy