Java代理的小例子
利用代理可以在运行时创建一个实现了一组给定接口的新类。
需要一个调用处理器(invocation handler),调用处理器需实现InvocationHandler接口。无论何时调用代理对象的方法,调用处理器的invoke方法都会被调用,并向其传递Method对象和原始的调用参数。
创建代理对象,需要使用Proxy类的newProxyInstance方法。此方法有三个参数:
1、一个类加载器(class loader),null代表默认
2、接口数组
3、一个调用处理器
使用代理的作用:
1、路由对远程服务器的方法调用
2、在程序运行期间,将用户接口事件与动作关联起来(spring AOP就是)
3、为调试,跟踪方法调用
下面的例子就是跟踪方法调用。以二分查找法为例,注:Integer实现comparable接口,代理类覆盖toString方法:
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Date; import java.util.Random; import javax.swing.JOptionPane; import javax.swing.Timer; public class TextMain { public static void main(String args[]) { Object[] elements=new Object[1000]; for(int i=0;i<elements.length;i++){ Integer value=i+1; InvocationHandler handler=new TraceHandler(value); Object proxy=Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler); elements[i]=proxy; } Integer key=new Random().nextInt(elements.length)+1; int result=Arrays.binarySearch(elements, key); if(result>=0)System.out.println(elements[result]); } } class TraceHandler implements InvocationHandler{ private Object target; public TraceHandler(Object t){ target=t; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.print(target); System.out.print("."+method.getName()+"("); 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(")"); return method.invoke(target, args); } }
运行结果:
500.compareTo(269) 250.compareTo(269) 375.compareTo(269) 312.compareTo(269) 281.compareTo(269) 265.compareTo(269) 273.compareTo(269) 269.compareTo(269) 269.toString() 269
InvocationHandler 中的invoke方法,定义了代理对象调用方法时希望执行的动作(跟踪,记录日志)
Proxy中newProxyInstance构造一个实现指定接口的代理类的实例,所有方法都将调用给定处理器对象的invoke方法。
所有代理类都扩展于proxy类,Proxy只有一个实例域——调用处理器InvocationHandler