java设计模式之 代理模式( 四 )


java设计模式之 代理模式

文章插图
所以我们可以设置sun.misc..这个系统属性为true来把生成的class保存到本地文件来查看 , 就是上面main方法中的.().put("sun.misc..", "true"); 。
到这里 , 可以大致的看清JDK中动态代理的面孔了 , 实现的步骤为:
创建代理类的源码;对源码进行编译成字节码;将字节码加载到内存;实例化代理类对象并返回给调用者;
运行完main方法后 , 我们到当前main方法的路径下的com/sun/proxy目录,可以看到有一个$.class,用jd-gui反编译查看:
package com.sun.proxy;import com.lbl.proxy.HelloWorld;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 Proxyimplements HelloWorld{private static Method m1;private static Method m3;private static Method m2;private static Method m0;public $Proxy0(InvocationHandler paramInvocationHandler)throws {super(paramInvocationHandler);}public final boolean equals(Object paramObject)throws {try{return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();}catch (RuntimeException localRuntimeException){throw localRuntimeException;}catch (Throwable localThrowable){}throw new UndeclaredThrowableException(localThrowable);}public final void sayHello(String paramString)throws {try{this.h.invoke(this, m3, new Object[] { paramString });return;}catch (RuntimeException localRuntimeException){throw localRuntimeException;}catch (Throwable localThrowable){}throw new UndeclaredThrowableException(localThrowable);}public final String toString()throws {try{return (String)this.h.invoke(this, m2, null);}catch (RuntimeException localRuntimeException){throw localRuntimeException;}catch (Throwable localThrowable){}throw new UndeclaredThrowableException(localThrowable);}public final int hashCode()throws {try{return ((Integer)this.h.invoke(this, m0, null)).intValue();}catch (RuntimeException localRuntimeException){throw localRuntimeException;}catch (Throwable localThrowable){}throw new UndeclaredThrowableException(localThrowable);}static{try{m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });m3 = Class.forName("com.lbl.proxy.HelloWorld").getMethod("sayHello", new Class[] { Class.forName("java.lang.String") });m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);return;}catch (NoSuchMethodException localNoSuchMethodException){throw new NoSuchMethodError(localNoSuchMethodException.getMessage());}catch (ClassNotFoundException localClassNotFoundException){}throw new NoClassDefFoundError(localClassNotFoundException.getMessage());}}
JDK动态代理为什么必须实现一个接口
从上面生产的代理类可以看到 , 生成的代理类是继承了Proxy类的 , 这就是说明了为什么使用JDK动态代理不能实现继承式动态代理 , 原因是Java不允许多继承 , 而生成的代理类本身就已经继承了Proxy类 。
我们自己模拟实现动态代理
根据上面源码的分析 ,  其实我们可以自己实现一个动态代理 。请参考另一篇文章自己动手模拟动态代理的实现
使用cglib实现动态代理
前面分析到 , 因为Java只允许单继承 , 而JDK生成的代理类本身就继承了Proxy类 , 因此 , 使用JDK实现的动态代理不能完成继承式的动态代理 , 但是我们可以使用cglib来实现继承式的动态代理 。
大名鼎鼎的中就含有cglib动态代理 , 在此也以中自带的cglib完成动态代理的实现: