【问题标题】:why does the method invoke() in InvocationHandler have an parameter Object proxy?为什么 InvocationHandler 中的方法 invoke() 有一个参数 Object 代理?
【发布时间】:2010-12-20 12:37:26
【问题描述】:

当你检查方法invoke(Object proxy, Method method, Object[] args)声明和doc语句时,你会发现输入参数proxy

proxy - 调用该方法的代理实例

当我对 java 动态代理进行测试时,我发现这个代理是由 vm 生成的。所以我想知道为什么方法调用有这个参数,除了它只是一个对象($proxy0 )但没有我们使用的实际操作?

【问题讨论】:

  • 对不起,可能你误解了我要表达的意思。我的意思是vm做的代理只是一个对象,它只是实现了接口数组中的所有接口(在方法Proxy.newProxyInstace( )). 但是这个 $proxy 对象只有方法但没有我们想要的真正动作,因为 vm 不知道我们想要做什么,不是吗?

标签: java dynamic proxy invoke


【解决方案1】:

如果您有多个代理对象的单个调用句柄,这将非常有用。因此,您可以使用哈希映射来存储代理状态信息。例如 - Mokito 测试框架存储代理调用历史。

【讨论】:

  • 谢谢,Alex。但是请您详细说明一下这个声明,尤其是关于哈希映射的事情吗?我认为处理程序是真正的代理或包装类来包装我们提供的做真正的业务的类。我说的对吗?
【解决方案2】:

如果你是中国人,你可以阅读这篇文章http://rejoy.iteye.com/blog/1627405

他做了$proxy0.class的反编译,你应该知道$proxy0扩展了Proxy

public final class $Proxy0 extends Proxy  
    implements UserService 

并且$proxy0中有一个函数:

public final void add()  
    {  
        try  
        {  
            //the h(invocationhandler) is in Proxy class,so we need pass this $proxy0 instance to super ,so the super(Proxy) can invoke($proxy0,method,args)
            super.h.invoke(this, m3, null);  
            return;  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  

【讨论】:

    【解决方案3】:

    我们可以使用 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 生成$proxy.class 文件。

    反编译.class文件,我们会发现这个类每个java方法(除了native方法)都被InvocationHandler调用

        public final boolean equals(Object var1) throws  {
            try {
                return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    

    super.h 对象是 InvocationHandler 实例。

    invocationHandler.invoke 中使用System.out.println(proxy) 会导致无限递归和StackOverflowException。

    所以我认为关于代理参数的唯一功能是使用getClass() 方法 获取GeneratedProxy.class信息,比如实现了哪些接口。

    在InvocationHandler调用方法实现中,我们可以知道代理对象的类型

    所以我们可以使用单个 InvocationHander 类来处理多个代理接口。

    【讨论】:

      猜你喜欢
      • 2015-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多