获取调用方方法(java.lang.reflect.method)
我想获取调用方法获取调用方方法(java.lang.reflect.method),java,reflection,Java,Reflection,我想获取调用方法java.lang.reflect.method非方法的名称 下面是一个如何获取callers类的示例 // find the callers class Thread t = Thread.getCurrentThread(); Class<?> klass = Class.forName(t.getStackTrace()[2].getClassName()); // do something with the class (like processing its
java.lang.reflect.method
非方法的名称
下面是一个如何获取callers类的示例
// find the callers class
Thread t = Thread.getCurrentThread();
Class<?> klass = Class.forName(t.getStackTrace()[2].getClassName());
// do something with the class (like processing its annotations)
...
//查找调用者类
线程t=Thread.getCurrentThread();
类klass=Class.forName(t.getStackTrace()[2].getClassName());
//对类执行一些操作(例如处理其注释)
...
这只是为了测试目的 非常简单:只需先获取相应的类对象,然后使用
Class.getMethod(字符串名、参数…)
希望这有帮助……我们几乎可以达到目的,这里有一种在很多情况下都有效的方法。问题是:如果存在重载方法(多个同名方法),它将无法可靠地工作。不幸的是,堆栈跟踪没有提供参数
private static Method getCallingMethod() throws ClassNotFoundException{
final Thread t = Thread.currentThread();
final StackTraceElement[] stackTrace = t.getStackTrace();
final StackTraceElement ste = stackTrace[2];
final String methodName = ste.getMethodName();
final String className = ste.getClassName();
Class<?> kls = Class.forName(className);
do{
for(final Method candidate : kls.getDeclaredMethods()){
if(candidate.getName().equals(methodName)){
return candidate;
}
}
kls = kls.getSuperclass();
} while(kls != null);
return null;
}
输出:
public static void main(final String[] args) throws Exception{
System.out.println(getCallingMethod());
}
公共静态void foo.bar.freeem.main(java.lang.String[])抛出java.lang.Exception
好的,这里有一个使用的解决方案。它几乎适用于所有情况:
private static Method getCallingMethod() throws ClassNotFoundException,
IOException{
final Thread t = Thread.currentThread();
final StackTraceElement[] stackTrace = t.getStackTrace();
final StackTraceElement ste = stackTrace[2];
final String methodName = ste.getMethodName();
final int lineNumber = ste.getLineNumber();
final String className = ste.getClassName();
final Class<?> kls = Class.forName(className);
final ClassReader cr = new ClassReader(className);
final EmptyVisitor empty = new EmptyVisitor();
final AtomicReference<Method> holder = new AtomicReference<Method>();
cr.accept(new ClassAdapter(empty){
@Override
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions){
return name.equals(methodName) ? new MethodAdapter(empty){
@Override
public void visitLineNumber(final int line,
final Label start){
if(line >= lineNumber && holder.get() == null){
final Type[] argumentTypes =
Type.getArgumentTypes(desc);
final Class<?>[] argumentClasses =
new Class[argumentTypes.length];
try{
for(int i = 0; i < argumentTypes.length; i++){
final Type type = argumentTypes[i];
final String dd = type.getDescriptor();
argumentClasses[i] = getClassFromType(type);
}
holder.set(kls.getDeclaredMethod(methodName,
argumentClasses));
} catch(final ClassNotFoundException e){
throw new IllegalStateException(e);
} catch(final SecurityException e){
throw new IllegalStateException(e);
} catch(final NoSuchMethodException e){
throw new IllegalStateException(e);
}
}
super.visitLineNumber(line, start);
}
private Class<?> getClassFromType(final Type type) throws ClassNotFoundException{
Class<?> javaType;
final String descriptor = type.getDescriptor();
if(type.equals(Type.INT_TYPE)){
javaType = Integer.TYPE;
} else if(type.equals(Type.LONG_TYPE)){
javaType = Long.TYPE;
} else if(type.equals(Type.DOUBLE_TYPE)){
javaType = Double.TYPE;
} else if(type.equals(Type.FLOAT_TYPE)){
javaType = Float.TYPE;
} else if(type.equals(Type.BOOLEAN_TYPE)){
javaType = Boolean.TYPE;
} else if(type.equals(Type.BYTE_TYPE)){
javaType = Byte.TYPE;
} else if(type.equals(Type.CHAR_TYPE)){
javaType = Character.TYPE;
} else if(type.equals(Type.SHORT_TYPE)){
javaType = Short.TYPE;
} else if(descriptor.startsWith("[")){
final Class<?> elementType =
getClassFromType(type.getElementType());
javaType =
Array.newInstance(elementType, 0).getClass();
} else{
javaType = Class.forName(type.getClassName());
}
return javaType;
}
}
: null;
}
},
0);
return holder.get();
}
私有静态方法getCallingMethod()抛出ClassNotFoundException,
IOException{
最终螺纹t=螺纹。当前螺纹();
最终StackTraceElement[]stackTrace=t.getStackTrace();
最终StackTraceElement ste=stackTrace[2];
最终字符串methodName=ste.getMethodName();
final int lineNumber=ste.getLineNumber();
最后一个字符串className=ste.getClassName();
最终类kls=Class.forName(类名称);
最终类读取器cr=新类读取器(类名称);
final EmptyVisitor empty=新的EmptyVisitor();
最终原子引用持有者=新原子引用();
cr.accept(新类适配器(空){
@凌驾
公共方法访客访问方法(
最终int访问,
最后一个字符串名,
最终字符串描述,
最后的字符串签名,
最终字符串[]例外){
返回名称.equals(methodName)?新MethodAdapter(空){
@凌驾
公共无效visitLineNumber(最终整数行,
最终标签(开始){
if(line>=lineNumber&&holder.get()==null){
最终类型[]参数类型=
Type.getArgumentTypes(desc);
期末班=
新类[argumentTypes.length];
试一试{
for(int i=0;i
我将把它留给您重构成可读的东西。如果调用方法的签名包含基本数组或多维数组,它将不起作用。显然,它只在类文件包含行号时起作用
啊,我工作了很久,然后我发现有人提出了一个几乎相同的解决方案!!!无论如何,我会留下我的,因为我是独立开发的。如果只是为了测试,那么这可能会起作用。它假设类文件可以通过调用类的
类加载器访问,并且类文件是comp带有调试符号的ILE(我希望它们是用于测试的!)。此代码依赖于
公共静态方法getMethod(最终StackTraceeElement StackTraceeElement)引发异常{
最后一个字符串stackTraceClassName=stackTraceeElement.getClassName();
最终字符串stackTraceMethodName=StackTraceeElement.getMethodNam
private static Method getCallingMethod() throws ClassNotFoundException,
IOException{
final Thread t = Thread.currentThread();
final StackTraceElement[] stackTrace = t.getStackTrace();
final StackTraceElement ste = stackTrace[2];
final String methodName = ste.getMethodName();
final int lineNumber = ste.getLineNumber();
final String className = ste.getClassName();
final Class<?> kls = Class.forName(className);
final ClassReader cr = new ClassReader(className);
final EmptyVisitor empty = new EmptyVisitor();
final AtomicReference<Method> holder = new AtomicReference<Method>();
cr.accept(new ClassAdapter(empty){
@Override
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions){
return name.equals(methodName) ? new MethodAdapter(empty){
@Override
public void visitLineNumber(final int line,
final Label start){
if(line >= lineNumber && holder.get() == null){
final Type[] argumentTypes =
Type.getArgumentTypes(desc);
final Class<?>[] argumentClasses =
new Class[argumentTypes.length];
try{
for(int i = 0; i < argumentTypes.length; i++){
final Type type = argumentTypes[i];
final String dd = type.getDescriptor();
argumentClasses[i] = getClassFromType(type);
}
holder.set(kls.getDeclaredMethod(methodName,
argumentClasses));
} catch(final ClassNotFoundException e){
throw new IllegalStateException(e);
} catch(final SecurityException e){
throw new IllegalStateException(e);
} catch(final NoSuchMethodException e){
throw new IllegalStateException(e);
}
}
super.visitLineNumber(line, start);
}
private Class<?> getClassFromType(final Type type) throws ClassNotFoundException{
Class<?> javaType;
final String descriptor = type.getDescriptor();
if(type.equals(Type.INT_TYPE)){
javaType = Integer.TYPE;
} else if(type.equals(Type.LONG_TYPE)){
javaType = Long.TYPE;
} else if(type.equals(Type.DOUBLE_TYPE)){
javaType = Double.TYPE;
} else if(type.equals(Type.FLOAT_TYPE)){
javaType = Float.TYPE;
} else if(type.equals(Type.BOOLEAN_TYPE)){
javaType = Boolean.TYPE;
} else if(type.equals(Type.BYTE_TYPE)){
javaType = Byte.TYPE;
} else if(type.equals(Type.CHAR_TYPE)){
javaType = Character.TYPE;
} else if(type.equals(Type.SHORT_TYPE)){
javaType = Short.TYPE;
} else if(descriptor.startsWith("[")){
final Class<?> elementType =
getClassFromType(type.getElementType());
javaType =
Array.newInstance(elementType, 0).getClass();
} else{
javaType = Class.forName(type.getClassName());
}
return javaType;
}
}
: null;
}
},
0);
return holder.get();
}
public static Method getMethod(final StackTraceElement stackTraceElement) throws Exception {
final String stackTraceClassName = stackTraceElement.getClassName();
final String stackTraceMethodName = stackTraceElement.getMethodName();
final int stackTraceLineNumber = stackTraceElement.getLineNumber();
Class<?> stackTraceClass = Class.forName(stackTraceClassName);
// I am only using AtomicReference as a container to dump a String into, feel free to ignore it for now
final AtomicReference<String> methodDescriptorReference = new AtomicReference<String>();
String classFileResourceName = "/" + stackTraceClassName.replaceAll("\\.", "/") + ".class";
InputStream classFileStream = stackTraceClass.getResourceAsStream(classFileResourceName);
if (classFileStream == null) {
throw new RuntimeException("Could not acquire the class file containing for the calling class");
}
try {
ClassReader classReader = new ClassReader(classFileStream);
classReader.accept(
new EmptyVisitor() {
@Override
public MethodVisitor visitMethod(int access, final String name, final String desc, String signature, String[] exceptions) {
if (!name.equals(stackTraceMethodName)) {
return null;
}
return new EmptyVisitor() {
@Override
public void visitLineNumber(int line, Label start) {
if (line == stackTraceLineNumber) {
methodDescriptorReference.set(desc);
}
}
};
}
},
0
);
} finally {
classFileStream.close();
}
String methodDescriptor = methodDescriptorReference.get();
if (methodDescriptor == null) {
throw new RuntimeException("Could not find line " + stackTraceLineNumber);
}
for (Method method : stackTraceClass.getMethods()) {
if (stackTraceMethodName.equals(method.getName()) && methodDescriptor.equals(Type.getMethodDescriptor(method))) {
return method;
}
}
throw new RuntimeException("Could not find the calling method");
}
public static Class<?> getClassFromType(Class<?> clazz, final Type type) throws ClassNotFoundException{
Class<?> javaType = null;
switch( type.getSort() ) {
case Type.VOID : javaType = Void.TYPE; break;
case Type.BOOLEAN : javaType = Boolean.TYPE; break;
case Type.CHAR : javaType = Character.TYPE; break;
case Type.BYTE : javaType = Byte.TYPE; break;
case Type.SHORT : javaType = Short.TYPE; break;
case Type.INT : javaType = Integer.TYPE; break;
case Type.FLOAT : javaType = Float.TYPE; break;
case Type.LONG : javaType = Long.TYPE; break;
case Type.DOUBLE : javaType = Double.TYPE; break;
case Type.ARRAY : javaType = Array.newInstance( getClassFromType( clazz, type.getElementType()), new int[type.getDimensions()] ).getClass(); break;
case Type.OBJECT : javaType = Class.forName( type.getClassName(), false, clazz.getClassLoader() ); break;
}
if ( javaType != null ) return javaType;
throw new ClassNotFoundException( "Couldn't find class for type " + type );
}