代理模式是常用的設計模式,其特征是代理類與委托類具有相同的接口,在具體實現上,有靜態代理和動態代理之分。代理類與委托類之間通常會存在關聯關系,一個代理類的對象與一個委托類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委托類的對象的相關方法,來提供特定的服務,也就是說代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事後處理消息等。
靜態代理和動態代理的一個顯著區別:
靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。
動態代理:動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。
靜態代理:
動態代理:
JDK動態代理解說:
java.lang.reflect包中的InvocationHandler接口和Proxy類提供了生成動態代理類的能力。
(1)InvocationHandler接口:
public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; }
參數說明:
Object proxy:指被代理的對象。
Method method:要調用的方法
Object[] args:方法調用時所需要的參數
可以將InvocationHandler接口的子類想象成一個代理的最終操作類,如上例中的定義的LogHandler類。
(2)Proxy類:
Proxy類是專門完成代理的操作類,可以通過此類為一個或多個接口動態地生成實現類,此類提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { Constructor cons = cl.getConstructor(constructorParams); return cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } }
參數說明:
ClassLoader loader:類加載器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子類實例
參看下面這篇文章中作者對上述源碼的分析
【原創】JDK動態代理,此次之後,永生難忘。 http://www.cnblogs.com/dreamroute/p/5273888.html
徹底理解JAVA動態代理 http://www.cnblogs.com/flyoung2008/p/3251148.html
擴展:
JDK的動態代理依靠接口實現,如果有些類並沒有實現接口,則不能使用JDK代理。
Spring AOP有兩種方式實現動態代理,如果基於接口編程,默認是JDK動態代理,否則就是cglib方式,另外spring的配置文件裡面也可以設置使用cglib來做動態代理。cglib的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。
注:此部分需查看cglib實現方式