【问题标题】:Java Dynamic Proxy - How reference concrete classJava 动态代理 - 如何引用具体类
【发布时间】:2011-07-07 05:37:31
【问题描述】:

我有一个关于 java 中的动态代理的问题。

假设我有一个名为Foo 的接口,其方法为execute,类为FooImpl implements Foo

当我为Foo 创建代理时,我有类似的东西:

Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                     new Class[] { Foo.class },
                                     handler);

假设我的调用处理程序如下所示:

public class FooHandler implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) {
        ...
    }
}

如果我的调用代码看起来像

Foo proxyFoo = (Foo) Proxy.newInstance(Foo.getClass().getClassLoader(),
                                       new Class[] { Foo.class },
                                       new FooHandler());
proxyFoo.execute();

如果代理可以从Foo接口拦截上述调用execute,那么FooImpl在哪里发挥作用?也许我以错误的方式看待动态代理。我想要的是能够从Foo 的具体实现中捕获execute 调用,例如FooImpl。这个可以吗?

非常感谢

【问题讨论】:

    标签: java dynamic proxy


    【解决方案1】:

    使用动态代理拦截方法的方式是:

    public class FooHandler implements InvocationHandler {
        private Object realObject;
    
        public FooHandler (Object real) {
            realObject=real;
        }
    
    
        public Object invoke(Object target, Method method, Object[] arguments) throws Throwable {
            if ("execute".equals(method.getName()) {
                // intercept method named "execute"
            }
    
            // invoke the original methods
            return method.invoke(realObject, arguments);
        }
    }
    

    通过以下方式调用代理:

    Foo foo = (Foo) Proxy.newProxyInstance(
                Foo.class.getClassLoader(),
                new Class[] {Foo.class}, 
                new FooHandler(new FooImpl()));
    

    【讨论】:

    • 谢谢大家。所以我的代码调用看起来像: Foo f = new FooImpl(); FooHandler fh = new FooHandler(f);对吗?
    • @Johan:我敢肯定你不是想在那里写new Foo(),因为首先 Foo 是一个接口。我认为应该是new FooHandler(new FooImpl())
    • 伙计们,最后一件事 - 为什么需要将 'Foo.class.getClassLoader()' 作为参数传递给 newProxyInstance 方法?那究竟是做什么的?谢谢
    • @Joeblackdev,在使用例如多个 jar 文件的环境中,它们将各自提供自己的类加载器,可能需要选择使用哪个。
    • @Joeblackdev:一个类在同一个类加载器中只“等于它自己”。如果Foo 被加载到其他CL 中,它将是一个不同的类。所以你要确保返回的Foo 不是来自其他类加载器,否则你会得到一个ClassCastException。代理不想依赖当前线程的上下文类加载器,因为这不能保证是您期望的。
    【解决方案2】:

    如果你想委托给像 FooImpl 这样的 Foo 实现,只需让你的 InvocationHandler 成为另一个 Foo 实例的包装器(传递给构造函数),然后发送一个 FooImpl 实例作为委托。然后,在 handler.invoke() 方法内部,调用 method.invoke(delegate, args)。

    【讨论】:

      猜你喜欢
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      相关资源
      最近更新 更多