【发布时间】:2019-11-07 14:17:00
【问题描述】:
我在读取代理类的方法注释时遇到问题。
方法上有接口、对象和注解,这部分真的很简单:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface A {
}
interface I {
void method();
}
class Test implements I {
@A
public void method() { }
}
接下来,有一个 InvocationHandler 什么都不做,只是简单地调用带有传递参数的方法:
class DefaultInvocationHandler implements InvocationHandler {
@Override
public Object invoke(final Object o, final Method method, final Object[] args) throws Throwable {
return method.invoke(o, args);
}
}
还有一个main 方法可以打印Test 实例的声明方法及其代理副本:
class Main {
public static void main(String[] args) {
Object test = new Test();
printMethods(test); // Outputs that `I#method` has `A` annotation
System.out.println();
Object proxied = Proxy.newProxyInstance(test.getClass().getClassLoader(), test.getClass().getInterfaces(), new DefaultInvocationHandler());
printMethods(proxied); // Outputs that `I#method` does not have `A` annotation
}
static void printMethods(Object obj) {
Arrays.stream(obj.getClass().getDeclaredMethods())
.forEach(method -> System.out.println(method.toString() + " has A annotation: " + method.isAnnotationPresent(A.class)));
}
}
问题来了:局部变量test是Test类的一个实例,而局部变量proxied实际上是一个Proxy,所以它的方法上没有任何注解。这是程序的输出:
public void Test.method() has A annotation: true // <- good thing
public final boolean $Proxy2.equals(java.lang.Object) has A annotation: false
public final java.lang.String $Proxy2.toString() has A annotation: false
public final void $Proxy2.method() has A annotation: false // <- bad thing
public final int $Proxy2.hashCode() has A annotation: false
我试过寻找解决方案,但this question 是关于从注释中提取注释(我想),this one 也是关于注释类的。 Some of them 是关于其他代理实现的。
➥ 那么,有没有办法从代理对象中获取实际注释,或者公开隐藏在代理下的类(不过我想要前一个)?
【问题讨论】:
-
如果您错过了请注意,在
method.invoke(o, args)中,o是Proxy实例。该调用将进入无限递归循环。 -
代理为什么要有
A注解?代理是I的实现,与Test类没有任何关系,那么为什么不相关类的注解会溢出到代理? -
@Holger,是的,现在我明白了,谢谢。几个小时前,我认为
Proxy是Test实例的包装器,但现在我看到它是InvocationHandler,它可能持有对代理对象的引用。在直接跳到示例之前,我应该阅读文档。 :D
标签: java reflection proxy