- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是“Thinking in Java”中经过修改的动态代理示例。
import java.lang.reflect.*;
interface Interface { void foo(); }
class RealObject implements Interface {
public void foo() {}
}
class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
proxy.toString();
return method.invoke(proxied, args);
}
}
public class ProxyTest {
public static void main(String args[]) {
RealObject real = new RealObject();
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(real));
proxy.foo();
}
}
在上面的例子中,我调用 toString()
里面的方法invoke()
方法。正如我所料,会发生无限递归,因为调用代理的 toString()
方法将再次调用 Handler。
Bruce Eckel 在《Thinking in Java》中是这样说的:
However, be careful when calling methods on the proxy inside
invoke()
, because calls through the interface are redirected through the proxy.
异常详细信息:
Exception in thread "main" java.lang.StackOverflowError
at DynamicProxyHandler.invoke(ProxyTest.java:19)
at $Proxy0.toString(Unknown Source)
at DynamicProxyHandler.invoke(ProxyTest.java:19)
at $Proxy0.toString(Unknown Source)
...
但是,如果我替换 proxy.getClass();
对于 proxy.toString();
:
public Object
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
proxy.getClass();
return method.invoke(proxied, args);
}
一切都好。没有堆栈溢出错误。没有无限递归。
我还尝试替换 proxy.toString();
与 proxy.hashCode();
或proxy.equals("foo");
。它们也导致了 StackOverflowError。
为什么是getClass()
不同于toString()
, hashCode()
,和equals()
?
最佳答案
答案可以在Proxy类的文档中找到:https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html
An invocation of the hashCode, equals, or toString methods declared in java.lang.Object on a proxy instance will be encoded and dispatched to the invocation handler's invoke method in the same manner as interface method invocations are encoded and dispatched, as described above. The declaring class of the Method object passed to invoke will be java.lang.Object. Other public methods of a proxy instance inherited from java.lang.Object are not overridden by a proxy class, so invocations of those methods behave like they do for instances of java.lang.Object.
另外,我认为这与 toString()
方法有一个默认定义有关:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
而getClass()
(以及wait()
、notify()
等)定义为:
public final native Class<?> getClass();
因此,要区分哪些方法不会被代理,您可以查看方法定义中是否存在 final native
。
关于java - 为什么我可以在 InvocableHandler 的 invoke() 方法中调用 proxy.getClass() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36097447/
我已经实现了一个动态代理,以便在我的方法开始之前执行一些操作。现在我在从代理类调用两个方法时遇到问题,代码如下: 动态代理类: public class IPageProxy implements I
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Dynamic proxy for concrete classes 一旦我创建了 InvocationHandle
这是“Thinking in Java”中经过修改的动态代理示例。 import java.lang.reflect.*; interface Interface { void foo(); } cl
我是一名优秀的程序员,十分优秀!