1. 程式人生 > >設計模式_代理模式_動態代理

設計模式_代理模式_動態代理

ride new http devel override 主題 引入 一個 技術

轉自:https://www.ibm.com/developerworks/cn/java/j-lo-proxy-pattern/index.html

動態代理是指在運行時動態生成代理類。即,代理類的字節碼將在運行時生成並載入當前代理的 ClassLoader。與靜態處理類相比,動態類有諸多好處。首先,不需要為真實主題寫一個形式上完全一樣的封裝類,假如主題接口中的方法很多,為每一個接口寫一個代理方法也很麻煩。如果接口有變動,則真實主題和代理類都要修改,不利於系統維護;其次,使用一些動態代理的生成方法甚至可以在運行時制定代理類的執行邏輯,從而大大提升系統的靈活性。

動態代理類使用字節碼動態生成加載技術,在運行時生成加載類。生成動態代理類的方法很多,如,JDK 自帶的動態處理

CGLIB、Javassist 或者 ASM 庫。JDK 的動態代理使用簡單,它內置在 JDK 中,因此不需要引入第三方 Jar 包,但相對功能比較弱。CGLIB 和 Javassist 都是高級的字節碼生成庫,總體性能比 JDK 自帶的動態代理好,而且功能十分強大。ASM 是低級的字節碼生成工具,使用 ASM 已經近乎於在使用 Java bytecode 編程,對開發人員要求最高,當然,也是性能最好的一種動態代理生成工具。但 ASM 的使用很繁瑣,而且性能也沒有數量級的提升,與 CGLIB 等高級字節碼生成工具相比,ASM 程序的維護性較差,如果不是在對性能有苛刻要求的場合,還是推薦 CGLIB 或者 Javassist。

以清單 1 所示代碼中的 DBQueryProxy 為例,使用動態代理生成動態類,替換上例中的 DBQueryProxy。首先,使用 JDK 的動態代理生成代理對象。JDK 的動態代理需要實現一個處理方法調用的 Handler,用於實現代理方法的內部邏輯。

 1 public class DBQueryHandler implements InvocationHandler {
 2     IDBQuery realQuery = null;//定義主題接口
 3 
 4     @Override
 5     public Object invoke(Object proxy, Method method, Object[] args)
6 throws Throwable { 7 //如果第一次調用,生成真實主題 8 if (realQuery == null) { 9 realQuery = new DBQuery(); 10 } 11 //返回真實主題完成實際的操作 12 return realQuery.request(); 13 } 14 15 }

設計模式_代理模式_動態代理