Java動態代理的示例詳解
定義
動態代理指的是,代理類和目標類的關系在程序運行的時候確定的,客戶通過代理類來調用目標對象的方法,是在程序運行時根據需要動態的創建目標類的代理對象。
分類
jdk動態代理
cglib動態代理
案例
需求
蘋果公司通過蘋果代理商來賣手機
方案一:jdk動態代理
定義抽象接口
/** * 售賣手機的接口(代理模式——抽象角色) * @author:liyajie * @createTime:2022/2/22 14:42 * @version:1.0 */ public interface IPhone { /** * 出售手機 * @author: liyajie * @date: 2022/2/22 14:44 * @param * @return void * @exception: * @update: * @updatePerson: **/ void sellPhone(); }
定義目標類實現接口,重寫接口方法
/** * 蘋果公司(代理模式——目標角色) * @author:liyajie * @createTime:2022/2/22 14:46 * @version:1.0 */ public class TargetPhone implements IPhone { @Override public void sellPhone() { System.out.println("蘋果公司正在出售手機"); } }
定義代理類
/** * 代理商(代理模式——代理角色) * @author:liyajie * @createTime:2022/2/22 14:50 * @version:1.0 */ public class ProxyPhone { private Object target; public ProxyPhone(Object target){ this.target = target; } public Object getProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK動態代理開始之前,添加業務邏輯XXX"); //使用反射機制來調用目標對象的方法:解決瞭問題二 Object invoke = method.invoke(target, args); System.out.println("JDK動態代理結束之後,添加業務邏輯XXX"); return invoke; } }); } }
定義測試類
/** * 測試類 * @author:liyajie * @createTime:2022/2/23 15:15 * @version:1.0 */ public class Test { public static void main(String[] args) { // 創建目標類 TargetPhone targetPhone = new TargetPhone(); // 創建代理類 IPhone iPhone = (IPhone) new ProxyPhone(targetPhone).getProxyInstance(); System.out.println(iPhone.getClass()); // 通過代理類調用目標方法 iPhone.sellPhone(); } }
查看測試結果
方案二:cglib動態代理
定義目標類
/** * 蘋果公司(代理模式——目標角色) * @author:liyajie * @createTime:2022/2/22 14:46 * @version:1.0 */ public class TargetPhone { public void sellPhone() { System.out.println("蘋果公司正在出售手機"); } }
定義代理工廠,用來獲取代理類
/** * 代理工廠 * @author:liyajie * @createTime:2022/2/23 15:32 * @version:1.0 */ public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target){ this.target = target; } public Object getProxyInstance(){ // 創建一個工具類 Enhancer enhancer = new Enhancer(); // 設置父類 enhancer.setSuperclass(target.getClass()); // 設置回調函數 enhancer.setCallback(this); // 創建子類對象,即代理對象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib動態代理開始之前,添加業務邏輯xxxx"); Object invoke = method.invoke(target, objects); System.out.println("cglib動態代理之後,添加業務邏輯"); return invoke; } }
定義測試類
/** * 測試類 * @author:liyajie * @createTime:2022/2/23 15:44 * @version:1.0 */ public class Test { public static void main(String[] args) { // 創建目標對象 TargetPhone targetPhone = new TargetPhone(); // 獲取代理對象 TargetPhone proxyInstance = (TargetPhone)new ProxyFactory(targetPhone).getProxyInstance(); // 通過代理對象調用具體的方法 proxyInstance.sellPhone(); } }
查看測試結果
分析
首先可以看到不管是jdk動態代理,還是cglib動態代理,實現的效果和靜態代理是一模一樣的,都實現瞭功能的擴展。但是兩種動態代理還是有些不同的,其中jdk動態代理需要目標對象實現接口,但是cglib動態代理不需要,因為他是在內存中構建一個子類對象,從而實現對目標對象的功能擴展。
總結
通過案例,我們瞭解瞭代理模式的幾種實現方式,下面我們總結下該模式:
優勢:
- 代理模式在客戶端和目標對象之間起到瞭一個中介和保護的作用
- 代理對象可以對目標對象進行功能的擴展和業務的擴展,增強目標對象
- 代理模式可以將客戶端和目標對象分離,在一定程度上降低瞭系統的耦合度
劣勢:
- 請求需要經過代理對象,會導致處理速度變慢
- 因為會有大量的代理對象產生,會增加系統的復雜度
到此這篇關於Java動態代理的示例詳解的文章就介紹到這瞭,更多相關Java 動態代理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!