【菜鳥學Java】13:代理模式——動態代理這樣玩!
在上篇部落格中,我們說到了代理模式的一種形式——靜態代理,文章結尾處提到了靜態代理的不足之處,其中有一個就是當我們的業務類非常多的時候,還用靜態代理顯然是一個非常糟糕的選擇,那麼這種情況該如何解決呢?這就引出了我們的動態代理。
什麼是動態代理?
所謂的動態代理是相對於靜態代理來講的,利用反射機制,在程式的運行期決定載入哪個類,很好的規避了靜態代理一個業務類對應一個代理類的問題。
為何用動態代理?
使用動態代理是為瞭解決靜態代理的擴充性差和維護困難的問題,這個在文章開頭就說的很明白了,
如何用動態代理?
要想使用動態代理,就必須使用Proxy(代理類)和InvocationHandler(反射)兩個東西了。我接著使用上篇部落格的例子為大家說明如何使用動態代理。
使用者管理的介面和實現就不再贅述了,下面請直接看動態代理類LogHandler和用戶端的代碼:
類比日誌功能的動態代理對象類LogHandler。代碼如下:
public class LogHandler implements InvocationHandler {//目標對象private Object targetObject;/** * 該類的執行個體化方法,用於將目標對象傳入 * @param targetObject 目標對象 * @return */public Object newProxyInstance(Object targetObject) {this.targetObject = targetObject;//調用Proxy類的靜態方法newProxyInstance執行個體化一個代理類,並且將目標對象作為參數傳入return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);}/** * 執行目標對象的方法 */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//在目標對象的方法執行之前列印一下System.out.println("開始執行方法-->>" + method.getName());for (int i=0; i
用戶端:
public class Client {/** * @param args */public static void main(String[] args) {//執行個體化動態代理類LogHandlerLogHandler logHandler = new LogHandler();//將使用者管理實作類別傳入動態代理類UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());//userManager.addUser("0001", "鐘躍民");//userManager.delUser("0001");String name = userManager.findUser("0001");System.out.println("Client.main() --- " + name);}}
小結一下:
動態代理與靜態代理相比較,最大的好處是介面中聲明的所有方法都被轉移到調用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在介面方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。而且動態代理的應用使我們的類職責更加單一,複用性更強。
無論是靜態代理和是動態代理,這種代理的思想,是十分有指導意義的。很多的架構和技術,都有代理的影子。比如Spring中的AOP(面向切面編程)的本質就是代理模式,還有SSH架構中的每一個架構都使用了代理模式。