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

      
      

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

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

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

                背景

                • 示例1:房東 ===> 目標(biāo)對(duì)象房屋中介 ===> 代理對(duì)象你,我 ===> 客戶端對(duì)象
                • 示例2:運(yùn)營商(電信,移動(dòng),聯(lián)通) ===> 目標(biāo)對(duì)象第三方公司 ===> 代理對(duì)象開發(fā)的應(yīng)用程序需要發(fā)送短信的功能(或者需要支付功能) ===> 客戶端對(duì)象

                代理模式的作用

                • 控制客戶對(duì)目標(biāo)對(duì)象的訪問
                • 增強(qiáng)訪問功能

                代理模式的分類

                靜態(tài)代理

                特點(diǎn)

                • 目標(biāo)對(duì)象和代理對(duì)象實(shí)現(xiàn)同一個(gè)業(yè)務(wù)接口
                • 目標(biāo)對(duì)象必須實(shí)現(xiàn)接口
                • 代理對(duì)象在程序運(yùn)行前就已經(jīng)存在

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

                業(yè)務(wù)背景

                分析

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

                代碼實(shí)現(xiàn)

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

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

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

                動(dòng)態(tài)代理

                JDK動(dòng)態(tài)代理

                特點(diǎn)

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

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

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

                Method類

                • 反射時(shí)用的類,用來進(jìn)行目標(biāo)對(duì)象的目標(biāo)方法的反射調(diào)用
                • method對(duì)象,接住我們正在調(diào)用的方法 sing(),show()method == sing(),show(),即:待調(diào)用的方法method.invoke() ==> 相當(dāng)于手工調(diào)用目標(biāo)方法 sing(),show();

                InvocationHandler接口

                • 用來實(shí)現(xiàn)代理和業(yè)務(wù)功能,我們?cè)谡{(diào)用時(shí)使用匿名內(nèi)部實(shí)現(xiàn)匿名內(nèi)部實(shí)現(xiàn):new接口的同時(shí),重寫接口中的方法(相當(dāng)于定義了該接口的一個(gè)實(shí)現(xiàn)類)

                Proxy類

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

                JDK動(dòng)態(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 { //目標(biāo)對(duì)象 Service target; public ProxyFactory(){} public ProxyFactory(Service target){ this.target = target; } //返回代理對(duì)象 public Object getAgent(){ return Proxy.newProxyInstance( //需要知道受代理對(duì)象的類信息 target.getClass().getClassLoader(), //需要知道受代理對(duì)象實(shí)現(xiàn)的所有接口信息 target.getClass().getInterfaces(), //反射調(diào)用目標(biāo)對(duì)象的目標(biāo)方法 new InvocationHandler() { @Override public Object invoke( Object obj, //用來反射調(diào)用方法 Method method, //待調(diào)用方法需要的參數(shù) Object[] args) throws Throwable { //擴(kuò)展業(yè)務(wù) System.out.println(“協(xié)商演出時(shí)間……”); System.out.println(“協(xié)商演出地點(diǎn)……”); //核心業(yè)務(wù),具體調(diào)用什么方法根據(jù)外層業(yè)務(wù)來反射調(diào)用對(duì)應(yīng)方法 Object res = method.invoke(target, args); //擴(kuò)展業(yè)務(wù) System.out.println(“協(xié)商演出費(fèi)用……”); //目標(biāo)對(duì)象執(zhí)行的目標(biāo)方法的返回值 return res; } } ); } }
                • 測(cè)試代碼示例
                • 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ù)需求動(dòng)態(tài)返回對(duì)應(yīng)類型的代理對(duì)象 Service agent = (Service) factory.getAgent(); //依托對(duì)應(yīng)類型的動(dòng)態(tài)代理對(duì)象完成業(yè)務(wù):擴(kuò)展業(yè)務(wù)(動(dòng)態(tài)代理對(duì)象完成) + 核心業(yè)務(wù)(目標(biāo)對(duì)象完成) 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); } }

                注意

                • 可被代理的方法應(yīng)該是受代理對(duì)象實(shí)現(xiàn)的所有接口中的方法與其所有實(shí)體方法的交集
                  • 本類中獨(dú)有的方法不被代理
                • 類型的轉(zhuǎ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()); } /* 輸出結(jié)果: 類型1: class com.example.service.impl.SuperStarLiu 類型2: class com.sun.proxy.$Proxy7 */
                鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年8月11日 09:25
                下一篇 2022年8月11日 09:25

                相關(guān)推薦

                聯(lián)系我們

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