【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
文章目錄
- 前言
- 一、靜態代理的弊端
- 二、動態代理的優勢
- 三、動態代理使用流程
- 1、目標對象接口
- 2、被代理對象
- 3、調用處理程序
- 4、客戶端
- 四、動態生成 代理對象 類 的 字節碼 文件數據
前言
代理模式結構 : 代理模式中的元素有 客戶端 , 主題對象 , 被代理對象 , 代理對象 ;
- 客戶端 持有 主題對象 , 調用其方法 ;
- 代理對象 和 被代理對象 都是 主題 的子類 ;
- 代理對象 持有 被代理對象 , 可以調用 被代理對象 的方法 ;
代理模式的核心 : 代理對象 與 被代理對象 都實現同一個父類或接口 , 這樣在客戶端使用時 , 客戶端 感覺自己與 被代理對象 溝通 , 但用戶實際上與 代理對象 進行溝通 ;
一、靜態代理的弊端
靜態代理 中 , 代理對象 和 被代理對象 必須實現 主題對象 接口 , 如果 主題對象 接口發生改變 , 則相應的 代理對象 和 被代理對象 都要進行相應修改 ;
二、動態代理的優勢
動態代理 解決了 靜態代理的上述問題 , 不需要手動創建代理對象 , 由 Java 虛擬機實現 代理對象 , 該代理對象自動實現 主題對象 的接口 ;
動態代理執行時 , 動態地創建了字節碼文件 , 生成了代理類 ;
三、動態代理使用流程
動態代理使用流程 :
-
① 創建目標對象 : 創建 目標對象 接口 ;
-
② 創建被代理對象 : 創建 被代理對象 , 實現 目標對象 接口 ;
-
③ 創建調用處理程序 : 創建 InvocationHandler 子類對象 , 內部持有 被代理對象 , 在 invoke 方法中 , 返回 method.invoke(subject, args) ;
-
④ 動態創建代理對象 : 調用 Proxy.newProxyInstance 創建 代理對象 實例對象 , 由 JVM 自動創建代理對象類 , 然后再創建對應的實例對象 ;
-
⑤ 動態代理調用 : 調用 代理對象 實例的相關 目標對象 接口 方法 ;
1、目標對象接口
/*** 目標接口* 代理對象 和 被代理對象 都要實現該接口*/ public interface Subject {void request(); }
2、被代理對象
/*** 被代理對象*/ public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("被代理對象 RealSubject request()");} }
3、調用處理程序
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;public class DynamicInvocationHandler implements InvocationHandler {/*** 持有的 被代理對象*/private Subject subject;public DynamicInvocationHandler(Subject subject) {this.subject = subject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 調用真實的 被代理對象 的方法// 被代理對象的所有的方法的調用都會傳到該方法中進行處理Object object = method.invoke(subject, args);return object;} }
4、客戶端
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {// 被代理對象Subject realSubject = new RealSubject();// 創建調用處理程序 , 內部持有被代理對象DynamicInvocationHandler dynamicInvocationHandler =new DynamicInvocationHandler(realSubject);// 生成動態代理類Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),dynamicInvocationHandler);// 動態代理調用subject.request();} }
執行結果 :
四、動態生成 代理對象 類 的 字節碼 文件數據
動態代理 中的 代理對象對應的 字節碼類 是由 Java 虛擬機自動生成的 , 在 java.lang.reflect.Proxy 中 , 調用 ProxyGenerator.generateProxyClass 方法 , 生成了 代理對象 類 , 返回的 byte[] 數據就是字節碼類對應的二進制數據 ;
/** Generate the specified proxy class.*/byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);ProxyGenerator 的源碼需要下載 JDK 源碼查看 , 在 IntelliJ IDEA 開發環境中無法查看 ;
網上找到了一篇博客 , 對此描述的很清楚 JDK動態代理[4]----ProxyGenerator生成代理類的字節碼文件解析 ;
ProxyGenerator 中的 generateProxyClass 方法中 , 主要調用了 generateClassFile 方法 , 按照 Class 字節碼的規范 , 按照順序依次寫入 魔數 , 次版本號 , 主版本號 , 常量池 , 訪問修飾符 , 類索引 等數據 ;
總結
以上是生活随笔為你收集整理的【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【设计模式】面向对象 - 多态 ( 面向
- 下一篇: 【设计模式】代理模式 ( 动态代理 |