一、JDK动态代理实现案例
Person接口
package com.zhoucong.proxy.jdk; public interface Person { // 寻找真爱 void findlove(); }
人物实现类
package com.zhoucong.proxy.jdk; public class Zhangsan implements Person{ @Override public void findlove() { System.out.println("我叫张三,性别女,我找对象的要求如下:\n"); System.out.println("高富帅"); System.out.println("有房有车"); System.out.println("身高180cm以上,体重70kg"); } }
代理类
package com.zhoucong.proxy.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MeiPo implements InvocationHandler{ private Person target; // 获取被代理人的个人资料 public Object getInstance(Person target) throws Exception { this.target = target; Class clazz = target.getClass(); System.out.println("被代理对象的class是:"+ clazz); return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); } @Override public Object invoke(Object arg0, Method method, Object[] args) throws Throwable { System.out.println("我是媒婆!!"); System.out.println("开始信息海选..."); System.out.println("-------------"); method.invoke(this.target, args); System.out.println("-------------"); System.out.println("如果合适的话,就准备办事"); return null; } }
运行测试
package com.zhoucong.proxy.jdk; public class TestFindLove { public static void main(String[] args) { try { Person obj = (Person) new MeiPo().getInstance(new Zhangsan()); System.out.println(obj.getClass()); obj.findlove(); /** * 原理: * 1.拿到被代理对象的引用,然后获取它的接口 * 2.jdk代理重新生成一个类,同时实现我们个额的代理对象所实现的接口 * 3.把被代理对象的引用也拿到了 * 4.重新动态生成一个class字节码 * 5.然后编译 */ } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
重点:
代理前对象为 com.zhoucong.proxy.jdk.Zhangsan
代理后获得的对象 com.sun.proxy.$Proxy0
二、原理分析
获取$Proxy0.class字节码内容
package com.zhoucong.proxy.jdk; import java.io.FileOutputStream; import sun.misc.ProxyGenerator; public class TestFindLove { public static void main(String[] args) { try { Person obj = (Person) new MeiPo().getInstance(new Zhangsan()); System.out.println(obj.getClass()); obj.findlove(); // 获取字节码内容 // ProxyGenerator需要导入jdk安装目录jre/bin下的rt.jar byte[] generateProxyClass = ProxyGenerator.generateProxyClass("$Proxy0", new Class[] { Person.class }); // 输出到本地 FileOutputStream os = new FileOutputStream("E:/GP_WORKSPACE/$Proxy0.class"); os.write(generateProxyClass); os.close(); } catch (Exception e) { e.printStackTrace(); } } }
利用反编译工具得到Java文件如下:
$Proxy0.java
import com.zhoucong.proxy.jdk.Person; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m2; private static Method m0; private static Method m3; public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final boolean equals(Object paramObject) { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void findlove() { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m3 = Class.forName("com.zhoucong.proxy.jdk.Person").getMethod("findlove", new Class[0]); return; } catch (NoSuchMethodException noSuchMethodException) { throw new NoSuchMethodError(noSuchMethodException.getMessage()); } catch (ClassNotFoundException classNotFoundException) { throw new NoClassDefFoundError(classNotFoundException.getMessage()); } } }
要点分析:
特点:1、JDK代理生成的类实现了Person接口继承父类Proxy
2、静态代码块获取了接口中的方法
m3 = Class.forName("com.zhoucong.proxy.jdk.Person").getMethod("findlove", new Class[0]);
3、JDK代理生成的类实现了接口方法,里面写了重要的一句话
this.h.invoke(this, m3, null);
分析:this.h 去父类Proxy中查看得知为父类的成员变量
/** * the invocation handler for this proxy instance. * @serial */ protected InvocationHandler h;
即MeiPo类并且调用了里面的Object invoke(Object arg0, Method method, Object[] args)方法
@Override public Object invoke(Object arg0, Method method, Object[] args) throws Throwable { System.out.println("我是媒婆!!"); System.out.println("开始信息海选..."); System.out.println("-------------"); // this.target.findlove(); //还可以写成如下,效果一样 method.invoke(this.target, args); System.out.println("-------------"); System.out.println("如果合适的话,就准备办事"); return null; }