在Java中利用代理(Proxy)可以在运行时创建一个实现了一组给定接口的新类。

    在系统程序设计中,有时需要面对无法确定接口,却需要构造对象的情况。以前为了解决此问题,有些程序根据动态确定的接口,生成Java类文件,然后调用类加载器构造该对象,然后使用,这样一来无可避免性能问题。通过代理类,能够在不额外创建Java文件的情况下构造对象及调用该对象方法。

    使用代理的理由有很多,其中就有如下的情况:

    1.路由对远程服务器的方法调用

    2.在程序运行期间,将用户接口事件与行动关联起来

    3.调试时跟踪方法调用

    以下举出一例,使用代理和调用处理器跟踪方法调用

import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.Arrays;
 import java.util.Random;
 
 public class ProxyTest
 {  
    public static void main(String[] args)
    {  
       Object[] elements = new Object[1000];
 
       // fill elements with proxies for the integers 1  1000
       for (int i = 0; i < elements.length; i++)
       {
          Integer value = i + 1;
          Class[] interfaces = value.getClass().getInterfaces();
          InvocationHandler handler = new TraceHandler(value);
          Object proxy = Proxy.newProxyInstance(null,
             interfaces, handler);
          elements[i] = proxy;
       }
 
       // construct a random integer
       Integer key = new Random().nextInt(elements.length) + 1;
 
       // search for the key
       int result = Arrays.binarySearch(elements, key);
 
       // print match if found
       if (result >= 0) System.out.println(elements[result]);
    }
 }
 
 /**
    An invocation handler that prints out the method name
    and parameters, then invokes the original method
 */
 class TraceHandler implements InvocationHandler
 { 
    /**
       Constructs a TraceHandler
       @param t the implicit parameter of the method call
    */
    public TraceHandler(Object t)
    {  
       target = t;
    }
 
    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable//此方法在代理类中的方法被调用时均会被调用
    { // print implicit argument
       System.out.print(target);
       // print method name
       System.out.print("." + m.getName() + "(");
       // print explicit arguments
       if (args != null)
       {
          for (int i = 0; i < args.length; i++)
          {  
             System.out.print(args[i]);
             if (i < args.length - 1)
                System.out.print(", ");
          }
       }
       System.out.println(")");
 
       // invoke actual method
 //      return new Integer("123");
       return m.invoke(target, args);
    }

    private Object target;
 }


 

  在此处,代理类取代了可能需要额外创建的Java文件。

  当调用代理类的方法时,调用实现InvocationHandler接口的方法invoke,此时可以针对传入参数Method的不同,定义不同的方法体(操作)

   Proxy类的特性:

   1.代理(Proxy)类只有一个实例变量,即调用处理器(InvocationHandler)

   2.代理类需要的额外数据都必须存储在调用处理器中

   3.代理类一定是public和final.

   4.如果代理类实现的所有接口都是public,则代理类就不属于某个特定的包;否则所有的非公有接口都必须属于同一个包,代理类也属于这个包(此设定的目的是确定代理类的所属包)

posted on 2011-08-15 01:55  星^_^風  阅读(200)  评论(0编辑  收藏  举报