利用代理可以在运行时创建一个实现了一组给定接口的新类: 这种功能只有在编译时无法确定需要实现哪个接口时才冇必要使用。
使用代理
代理类能够实现指定的接口。它具有下列方法 :
- 指定接口所需要的全部方法
- Object类中的全部方法,例如 toString 、 equals 等
调用处理器是实现了 InvocationHandler 接口的类对象 。 在这个接口中只有一个方法 :
Object invoke ( Object proxy , Method method , Object[]args )
创建代理对象
要想创建一个代理对象 , 需要使用 Proxy 类的 newProxylnstance 方法 。 这个方法有三个参数 :
- 一个类加栽器 ( class loader ) 。用 null 表示使用默认的类加载器
- 一个 Class 对象数组 , 每个元素都是需要实现的接口 。
- 一个调用处理器
使用代理场景:
- 路由对远程服务器的方法调用
- 在程序运行期间, 将用户接口事件与动作关联起来 。
- 为调试 ,跟踪方法调用
一个调用二分查找并在代理中invoke方法中打印参数和方法名称的示例代码:
public class TestProxy {
public static void main(String[] args) {
Class<?>[] interfaces = new Class<?>[]{Comparable.class};
Object[] elements = new Object[1000];
for(int i=0;i< elements.length;i++){
Integer va = i+1;
elements[i]=Proxy.newProxyInstance(null,interfaces,new TraceHandler(va));
}
int result = Arrays.binarySearch(elements, 288);
System.out.println("result:"+elements[result]);
}
}
class TraceHandler implements InvocationHandler{
final private Object target;
TraceHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.print(target);
System.out.print("."+method.getName());
if(args!=null){
for(Object o:args){
System.out.print(","+o);
}
}
System.out.println();
return method.invoke(target,args);
}
}
程序输出结果:
500.compareTo,288
250.compareTo,288
375.compareTo,288
312.compareTo,288
281.compareTo,288
296.compareTo,288
288.compareTo,288
288.toString
result:288