package com.itcast.day3; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; /* * 三种得到代理类对象的方式 * 一、直观型 * 二、匿名内部类型 * 三、从字节码一步到位型(推荐使用) */ public class ProxyTest { public static void main(String[] args)throws Exception { //得到代理类的字节码 Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); //clazzProxy1.newInstance();//不能这么干,因为该newInstance调用的是那个不带参数的构造方法 /**一、最直观的方式创建代理类对象***/ //01.得到有参数的构造方法 System.out.println("begin create instance"); Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class); //newInstance时要有InvocationHandler实例,但是InvocationHandler是一个接口,所以定义了这个类 class InvocationHandlerImpl_1 implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } } //02.得到实例对象 Collection proxy1=(Collection) constructor.newInstance(new InvocationHandlerImpl_1()); System.out.println(proxy1.toString());// proxy1.clear();//无返回值函数 //proxy1.size();//有返回值函数--报空指针--没有目标类 /**二、使用匿名内部类得到代理类对象****/ Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }); /**三、一步到位得到代理类对象****/ Collection proxy3 = (Collection)Proxy.newProxyInstance( Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler(){ ArrayList target=new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long beginTime=System.currentTimeMillis(); Object reVal=method.invoke(target, args); long endTime=System.currentTimeMillis(); System.out.println(method.getName()+" running "+(endTime-beginTime)); return reVal; } } ); proxy3.add("123"); proxy3.add("456"); System.out.println(proxy3.size()); System.out.println(proxy3.getClass().getName());//com.sun.proxy.$Proxy0,为什么不是ArrayList? //原因 Object没有把所有的方法都派发给 代理类构造方法的参数---InvocationHandler来处理 /* java.lang.reflect.Proxy API 在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法的调用将按照与编码 和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的 invoke 方法,如上所述。 传递到 invoke 的 Method 对象的声明类是 java.lang.Object。 代理类不重写从 java.lang.Object 继承的代理实例的其他公共方法, 所以这些方法的调用行为与其对 java.lang.Object 实例的操作一样。 */ } }