利用代理可以在运行时
创建一个实现了一组给定接口的新类。这种功能只有在编译时无法确定需要实现哪个接口才有必要使用。
代理类能够实现指定的接口
1.指定接口所需的全部方法。
2.Object类的全部方法。
实现代理特性
1.调用处理器
然而,不能在运行时定义这些方法的新代码,而是要提供一个调用处理器,调用处理器实现了InvocationHandler接口的对象,在这个接口只有一个方法
Object invoke(Object proxy,Method method,Object []args)
无论何时调用代理对象的方法,调用处理器的invoke方法都回被调用,并向其传递Method对象和原始的调用参数,调用处理器必须给出处理调用的方式。
2.创建代理对象
需要使用Proxy的newProxyInstance方法,该方法有三个参数
1.类加载器
2.Class对象数组,每个元素都是需要实现的接口
3.调用处理器
例题:使用代理对象对二分查找进行跟踪
首先将用1-1000整数的代理填充数组,然后调用Arrays类中的binarySearch方法在数组中查找一个随机整数,最后,打印与之匹配的元素。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;
import question.tahm;
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Object []elements=new Object[100];
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;
}
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
{
public TraceHandler(Object o)
{
target=o;
}
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
// TODO Auto-generated method stub
System.out.print(target);
System.out.print("."+arg1.getName()+"(");
if(arg2!=null)
{
for(int i=0;i<arg2.length;i++)
{
System.out.print(arg2[i]);
if(i<arg2.length-1)
System.out.print(".");
}
}
System.out.println(")");
return arg1.invoke(target, arg2);
}
private Object target;
}
运行结果:
50.compareTo(26)
25.compareTo(26)
37.compareTo(26)
31.compareTo(26)
28.compareTo(26)
26.compareTo(26)
26.toString()
26
代理类的特性:
代理是在运行过程中创建的,但是一旦创建就和普通类没什么区别