亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                mybatis : 靜態(tài)代理 + jdk動態(tài)代理

                mybatis : 靜態(tài)代理 + jdk動態(tài)代理

                背景

                • 有時目標對象不可直接訪問,只能通過代理對象訪問
                • 圖示:
                • 示例1:房東 ===> 目標對象房屋中介 ===> 代理對象你,我 ===> 客戶端對象
                • 示例2:運營商(電信,移動,聯(lián)通) ===> 目標對象第三方公司 ===> 代理對象開發(fā)的應用程序需要發(fā)送短信的功能(或者需要支付功能) ===> 客戶端對象

                代理模式的作用

                • 控制客戶對目標對象的訪問
                • 增強訪問功能

                代理模式的分類

                靜態(tài)代理

                特點

                • 目標對象和代理對象實現(xiàn)同一個業(yè)務接口
                • 目標對象必須實現(xiàn)接口
                • 代理對象在程序運行前就已經存在

                靜態(tài)代理示例與原理分析

                業(yè)務背景

                分析

                • 定義業(yè)務接口:面向接口編程,定義業(yè)務
                • 目標對象實現(xiàn)接口:業(yè)務的核心功能到底怎么實現(xiàn)
                • 代理對象(擴展業(yè)務 + 核心業(yè)務)實現(xiàn)了目標對象所實現(xiàn)的接口,說明代理對象有資歷進行代理對核心業(yè)務進行擴展調用目標對象實現(xiàn)核心業(yè)務(只能目標對象自己完成)
                • 客戶:無法直接訪問目標對象,要訪問代理對象

                代碼實現(xiàn)

                • 面向接口編程
                  • 成員變量是接口類型
                  • 傳入目標對象,方法參數(shù)設計為接口
                  • 調用時,接口指向實現(xiàn)類
                • 靜態(tài)代理對象代碼
                • package com.example.service.impl; import com.example.service.Service; public class Agent implements Service { //定義接口對象 public Service target; public Agent(){} //傳入接口對象 public Agent(Service target){ this.target = target; } @Override public void sing() { System.out.println(“協(xié)商演出時間……”); System.out.println(“協(xié)商演出地點……”); //目標對象完成核心業(yè)務,接口指向實現(xiàn)類,調用實現(xiàn)類的方法 target.sing(); System.out.println(“協(xié)商演出費用……”); } }

                靜態(tài)代理優(yōu)缺點

                • 優(yōu)點:能夠靈活地進行目標對象的切換適用于業(yè)務固定,目標對象可靈活切換的場景
                • 缺點:無法進行功能的靈活處理,當業(yè)務發(fā)生改變時,所有涉及到的實現(xiàn)類代碼和代理對象代碼都要改變

                動態(tài)代理

                JDK動態(tài)代理

                特點

                • 目標對象必須實現(xiàn)業(yè)務接口
                • JDK代理對象不需要實現(xiàn)業(yè)務接口
                • JDK代理對象在程序運行前不存在,程序運行時動態(tài)的在內存中構建(根據(jù)受代理的對象動態(tài)創(chuàng)建)
                • JDK動態(tài)代理可以靈活的進行業(yè)務功能的切換

                JDK動態(tài)代理用到的類和接口

                • 使用現(xiàn)有的工具類完成JDK動態(tài)代理
                • 先了解兩個單詞的意思InvocationHandler:調用處理程序invoke:調用

                Method類

                • 反射時用的類,用來進行目標對象的目標方法的反射調用
                • method對象,接住我們正在調用的方法 sing(),show()method == sing(),show(),即:待調用的方法method.invoke() ==> 相當于手工調用目標方法 sing(),show();

                InvocationHandler接口

                • 用來實現(xiàn)代理和業(yè)務功能,我們在調用時使用匿名內部實現(xiàn)匿名內部實現(xiàn):new接口的同時,重寫接口中的方法(相當于定義了該接口的一個實現(xiàn)類)

                Proxy類

                • 位于:java.lang.reflect.Proxy包下
                • 有一個核心方法:Proxy.newProxyInstance(….),專門獲取動態(tài)代理對象,有三個參數(shù)
                  • 參數(shù)1:ClassLoader loader
                    • 目標對象的類加載器
                    • 目的:獲取類方法等信息,畢竟底層還是要調用受代理對象所實現(xiàn)的方法
                    • 傳入:targetObj.getClass().getClassLoader();
                  • 參數(shù)2:Class[] interfaces
                    • 目標對象實現(xiàn)的所有接口,類的接口可以有多個
                    • 目的:獲取目標對象實現(xiàn)的所有接口以及接口的相關信息,畢竟底層要知道目標對象都可以完成哪些業(yè)務操作
                    • 傳入:targetObj.getClass().getInterfaces();
                  • 上面兩個參數(shù)為代理對象動態(tài)的創(chuàng)建和調用目標對象的方法提供了數(shù)據(jù)支持,第3個參數(shù)相當于調用程序
                  • 參數(shù)3:InvocationHandler
                    • 實現(xiàn)代理功能的接口,這里代理功能包括:擴展的功能 + 核心業(yè)務功能,傳入的匿名內部實現(xiàn)如下
                  • new InvocationHandler() { @Override public Object invoke( Object obj, //用來反射調用方法 Method method, //待調用方法需要的參數(shù) Object[] args) throws Throwable { //擴展業(yè)務 System.out.println(“協(xié)商演出時間……”); System.out.println(“協(xié)商演出地點……”); //核心業(yè)務,具體調用什么方法根據(jù)外層業(yè)務來反射調用對應方法 Object res = method.invoke(target, args); //擴展業(yè)務 System.out.println(“協(xié)商演出費用……”); //目標對象執(zhí)行的目標方法的返回值 return res; } }

                JDK動態(tài)代理示例

                • 代理工廠代碼
                • package com.example.proxy; import com.example.service.Service; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { //目標對象 Service target; public ProxyFactory(){} public ProxyFactory(Service target){ this.target = target; } //返回代理對象 public Object getAgent(){ return Proxy.newProxyInstance( //需要知道受代理對象的類信息 target.getClass().getClassLoader(), //需要知道受代理對象實現(xiàn)的所有接口信息 target.getClass().getInterfaces(), //反射調用目標對象的目標方法 new InvocationHandler() { @Override public Object invoke( Object obj, //用來反射調用方法 Method method, //待調用方法需要的參數(shù) Object[] args) throws Throwable { //擴展業(yè)務 System.out.println(“協(xié)商演出時間……”); System.out.println(“協(xié)商演出地點……”); //核心業(yè)務,具體調用什么方法根據(jù)外層業(yè)務來反射調用對應方法 Object res = method.invoke(target, args); //擴展業(yè)務 System.out.println(“協(xié)商演出費用……”); //目標對象執(zhí)行的目標方法的返回值 return res; } } ); } }
                • 測試代碼示例
                • package com.example.proxy; import com.example.service.Service; import com.example.service.impl.SuperStarZhou; import org.junit.Test; public class TestProxyFactory { @Test public void testGetProxy(){ //確定客戶需求 ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); //根據(jù)需求動態(tài)返回對應類型的代理對象 Service agent = (Service) factory.getAgent(); //依托對應類型的動態(tài)代理對象完成業(yè)務:擴展業(yè)務(動態(tài)代理對象完成) + 核心業(yè)務(目標對象完成) agent.sing(); } @Test public void testGetProxy2(){ ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); Service agent = (Service) factory.getAgent(); String res = (String) agent.show(60); System.out.println(res); } }

                注意

                • 可被代理的方法應該是受代理對象實現(xiàn)的所有接口中的方法與其所有實體方法的交集
                  • 本類中獨有的方法不被代理
                • 類型的轉變
                • @Test public void testGetProxy2() { ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); Service agent = (Service) factory.getAgent(); Service liu = new SuperStarLiu(); System.out.println(“類型1: ” + liu.getClass()); System.out.println(“類型2: ” + agent.getClass()); } /* 輸出結果: 類型1: class com.example.service.impl.SuperStarLiu 類型2: class com.sun.proxy.$Proxy7 */
                鄭重聲明:本文內容及圖片均整理自互聯(lián)網,不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年8月11日 09:25
                下一篇 2022年8月11日 09:25

                相關推薦

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時間:周一至周五,10:30-18:30,節(jié)假日休息