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

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

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

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

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

    3.调试时跟踪方法调用

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

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 import java.util.Arrays;
 5 import java.util.Random;
 6 
 7 public class ProxyTest
 8 {  
 9    public static void main(String[] args)
10    {  
11       Object[] elements = new Object[1000];
12 
13       // fill elements with proxies for the integers 1  1000
14       for (int i = 0; i < elements.length; i++)
15       {
16          Integer value = i + 1;
17          Class[] interfaces = value.getClass().getInterfaces();
18          InvocationHandler handler = new TraceHandler(value);
19          Object proxy = Proxy.newProxyInstance(null,
20             interfaces, handler);
21          elements[i] = proxy;
22       }
23 
24       // construct a random integer
25       Integer key = new Random().nextInt(elements.length) + 1;
26 
27       // search for the key
28       int result = Arrays.binarySearch(elements, key);
29 
30       // print match if found
31       if (result >= 0) System.out.println(elements[result]);
32    }
33 }
34 
35 /**
36    An invocation handler that prints out the method name
37    and parameters, then invokes the original method
38 */
39 class TraceHandler implements InvocationHandler
40 
41    /**
42       Constructs a TraceHandler
43       @param t the implicit parameter of the method call
44    */
45    public TraceHandler(Object t)
46    {  
47       target = t;
48    }
49 
50    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable//此方法在代理类中
51    {                                                             //的方法被调用时均会被调用
52       // print implicit argument
53       System.out.print(target);
54       // print method name
55       System.out.print("." + m.getName() + "(");
56       // print explicit arguments
57       if (args != null)
58       {
59          for (int i = 0; i < args.length; i++)
60          {  
61             System.out.print(args[i]);
62             if (i < args.length - 1)
63                System.out.print("");
64          }
65       }
66       System.out.println(")");
67 
68       // invoke actual method
69 //      return new Integer("123");
70       return m.invoke(target, args);
71    }
72 
73    private Object target;
74 }
75

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

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

   Proxy类的特性:

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

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

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

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