java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler

时间:2018-05-22 07:19:14

标签: java reflection proxy

java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler的目的是什么? 当我们需要在我们的应用程序中创建和使用它们时?

1 个答案:

答案 0 :(得分:2)

代理是一种设计模式。当我们想要添加或修改现有类的某些功能时,我们创建并使用代理对象。使用代理对象而不是原始代理对象。通常,代理对象具有与原始代理对象相同的方法,并且在Java代理类中通常扩展原始类。代理有一个原始对象的句柄,可以调用该方法。

这样,代理类可以方便地实现许多功能:

  1. 在方法启动和停止时记录
  2. 对参数执行额外检查
  3. 模仿原始类的行为
  4. 获取昂贵的资源
  5. 不修改类的原始代码。 (以上列表并不广泛,仅列出一些例子)。

    要创建实际的动态代理类,您需要做的就是实现java.lang.reflect.InvocationHandler接口:

    public Class MyDynamicProxyClass implements
    java.lang.reflect.InvocationHandler
    {
      Object obj;
      public MyDynamicProxyClass(Object obj)
      { this.obj = obj; }
      public Object invoke(Object proxy, Method m, Object[] args) throws
    Throwable
      {
        try {
          // do something
        } catch (InvocationTargetException e) {
          throw e.getTargetException();
        } catch (Exception e) {
          throw e;
        }
        // return something
      }
    }
    

    这就是它的全部内容!好吧,你还需要拥有真正的代理接口:

    public interface MyProxyInterface
    {
      public Object MyMethod();
    }
    

    然后实际使用该动态代理,代码如下所示:

    MyProxyInterface foo = (MyProxyInterface)
    java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                                             Class[] { MyProxyInterface.class },
                                             new MyDynamicProxyClass(obj));
    

    知道上面的代码非常难看,我想把它隐藏在某种工厂方法中。因此,我不会在客户端代码中使用那些混乱的代码,而是将该方法添加到MyDynamicProxyClass中:

    static public Object newInstance(Object obj, Class[] interfaces)
    {
      return
    java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                                                      interfaces,
                                                      new
    MyDynamicProxyClass(obj));
    }
    That allows me to use the following client code instead:
    
    MyProxyInterface foo = (MyProxyInterface)
      MyDynamicProxyClass.newInstance(obj, new Class[]
    { MyProxyInterface.class });
    

    这是更清洁的代码。将来有一个完全隐藏客户端代码的工厂类可能是一个好主意,因此客户端代码看起来更像:

    MyProxyInterface foo = Builder.newProxyInterface();
    

    总的来说,实现动态代理非常简单。

    参考: