利用代理可以在运行时创建一个实现了一组给定接口的新类。
需要一个调用处理器(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
来源:https://www.cnblogs.com/qiaomu/p/4378255.html