黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) hot資訊 秒懂動(dòng)態(tài)代理的三種實(shí)現(xiàn)方法

秒懂動(dòng)態(tài)代理的三種實(shí)現(xiàn)方法

更新時(shí)間:2022-04-20 10:43:05 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽892次

代理模式是一種結(jié)構(gòu)類型的設(shè)計(jì)模式,它提供了另一種方式是通過(guò)代理訪問(wèn)目標(biāo)對(duì)象的對(duì)象。

這樣做的優(yōu)點(diǎn)是:實(shí)現(xiàn)目標(biāo)對(duì)象的基礎(chǔ)上,額外的功能操作可以提高,也就是說(shuō),目標(biāo)對(duì)象可以擴(kuò)展的功能。

這里使用一個(gè)想法在編程:不要修改代碼或別人寫的方法。如果你需要修改它,您可以擴(kuò)展代理的方法。

代理模型有三個(gè)角色:

真正的主題:真正的類,也就是說(shuō),代理類和委托類。用來(lái)真正完整的業(yè)務(wù)服務(wù)功能;

代理:代理類實(shí)現(xiàn)自己的請(qǐng)求的函數(shù)對(duì)應(yīng)于真正的主題,和代理類對(duì)象并沒(méi)有真正實(shí)現(xiàn)其業(yè)務(wù)功能;

主題:定義RealSubject和代理的角色應(yīng)該實(shí)現(xiàn)的接口。

有三種類型的代理模式,靜態(tài)代理,動(dòng)態(tài)代理(JDK代理、接口代理),Cglib代理(子類創(chuàng)建的目標(biāo)對(duì)象是動(dòng)態(tài)內(nèi)存)

靜態(tài)代理

靜態(tài)代理首先需要定義接口,代理對(duì)象和代理對(duì)象實(shí)現(xiàn)相同的接口,然后調(diào)用目標(biāo)對(duì)象的方法通過(guò)調(diào)用相同的方法。

可以看到,代理類只不過(guò)是添加一些操作調(diào)用委托類方法之前和之后。主要類的差異也會(huì)導(dǎo)致不同的代理類。

某公司生產(chǎn)電視機(jī),需要找一個(gè)代理在當(dāng)?shù)氐匿N售。當(dāng)客戶需要買電視,他可以直接通過(guò)代理購(gòu)買。

代碼示例:

電視:

public class TV {
    private String name;//名稱
    private String address;//生產(chǎn)地
    public TV(String name, String address) {
        this.name = name;
        this.address = address;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "TV{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

創(chuàng)建公司的接口:

public interface TVCompany {
    /**
     * 生產(chǎn)電視機(jī)
     * @return 電視機(jī)
     */
    public TV produceTV();
}

公司的工廠生產(chǎn)電視機(jī):

public class TVFactory implements TVCompany {
    @Override
    public TV produceTV() {
        System.out.println("TV factory produce TV...");
        return new TV("小米電視機(jī)","合肥");
    }
}

代理地方訂單的貨物(靜態(tài)代理類型):

public class TVProxy implements TVCompany{
    private TVCompany tvCompany;
    public TVProxy(){
    }
    @Override
    public TV produceTV() {
        System.out.println("TV proxy get order .... ");
        System.out.println("TV proxy start produce .... ");
        if(Objects.isNull(tvCompany)){
            System.out.println("machine proxy find factory .... ");
            tvCompany = new TVFactory();
        }
        return tvCompany.produceTV();
    }
}

消費(fèi)者獲得商品通過(guò)代理(代理)的使用:

public class TVConsumer {
    public static void main(String[] args) {
        TVProxy tvProxy = new TVProxy();
        TV tv = tvProxy.produceTV();
        System.out.println(tv);
    }
}

輸出結(jié)果:

TV proxy get order .... 
TV proxy start produce .... 
machine proxy find factory .... 
TV factory produce TV...
TV{name='小米電視機(jī)', address='合肥'}
Process finished with exit code 0

優(yōu)點(diǎn):靜態(tài)代理模式實(shí)現(xiàn)的功能擴(kuò)張目標(biāo)對(duì)象不改變目標(biāo)對(duì)象。

缺點(diǎn):靜態(tài)代理實(shí)現(xiàn)所有目標(biāo)對(duì)象的方法。一旦方法被添加到目標(biāo)接口,代理對(duì)象和目標(biāo)對(duì)象必須做出相應(yīng)調(diào)整,從而增加維護(hù)成本。

如何解決靜態(tài)代理的缺點(diǎn)嗎?答案是,您可以使用動(dòng)態(tài)代理

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

動(dòng)態(tài)代理有以下特點(diǎn):

JDK動(dòng)態(tài)代理對(duì)象不需要實(shí)現(xiàn)接口,只有目標(biāo)對(duì)象需要實(shí)現(xiàn)的接口。

實(shí)現(xiàn)動(dòng)態(tài)代理基于接口,您需要使用JDK動(dòng)態(tài)構(gòu)建的API在JVM內(nèi)存代理對(duì)象。

需要使用數(shù)組。代理,其newProxyInstance方法,但這種方法需要接收三個(gè)參數(shù)。

注意,這個(gè)方法在代理類是一個(gè)靜態(tài)方法,和接收三個(gè)參數(shù):

類加載器加載程序:指定當(dāng)前目標(biāo)對(duì)象使用類加載器,并獲得的方法加載程序是固定的。

類< ?>[]接口:接口實(shí)現(xiàn)的目標(biāo)對(duì)象的類型,和通用方法用于確定類型。

InvocationHandler h:事件處理,執(zhí)行目標(biāo)對(duì)象的方法時(shí),會(huì)觸發(fā)事件處理程序的方法,目前執(zhí)行的目標(biāo)對(duì)象的方法將會(huì)作為一個(gè)參數(shù)傳遞。

一天,公司業(yè)務(wù)增加,越來(lái)越多的產(chǎn)品銷售,并需要更多的售后。但該公司發(fā)現(xiàn),原來(lái)的代理必須重新訓(xùn)練完成的所有業(yè)務(wù),所以它發(fā)現(xiàn)另一個(gè)動(dòng)態(tài)無(wú)縫連接劑B劑B承諾所有的公司的業(yè)務(wù),無(wú)論如何添加新業(yè)務(wù),它可以完成沒(méi)有額外的培訓(xùn)。

代碼示例:

public interface TVCompany {
    /**
     * 生產(chǎn)電視機(jī)
     * @return 電視機(jī)
     */
    public TV produceTV();
    /**
     * 維修電視機(jī)
     * @param tv 電視機(jī)
     * @return 電視機(jī)
     */
    public TV repair(TV tv);
}

工廠也開(kāi)始維護(hù)業(yè)務(wù):

public class TVFactory implements TVCompany {
    @Override
    public TV produceTV() {
        System.out.println("TV factory produce TV...");
        return new TV("小米電視機(jī)","合肥");
    }
    @Override
    public TV repair(TV tv) {
        System.out.println("tv is repair finished...");
        return new TV("小米電視機(jī)","合肥");
    }
}

B代理全面代理公司的業(yè)務(wù)。使用代理。newProxyInstance方法生成一個(gè)代理對(duì)象在調(diào)用方法,實(shí)現(xiàn)InvocationHandler反映在代理類的方法調(diào)用通過(guò)調(diào)用方法,并提供一個(gè)增強(qiáng)的方法。

public class TVProxyFactory {
    private Object target;
    public TVProxyFactory(Object o){
        this.target = o;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("TV proxy find factory for tv.... ");
                Object invoke = method.invoke(target, args);
                return invoke;
            }
        });
    }
}

購(gòu)買和修理這兩個(gè)服務(wù)B代理可以直接完成。如果公司提高其業(yè)務(wù)后,代理B可以做同樣的事情。

public class TVConsumer {
    public static void main(String[] args) {
        TVCompany target = new TVFactory();
        TVCompany tvCompany = (TVCompany) new TVProxyFactory(target).getProxy();
        TV tv = tvCompany.produceTV();
        tvCompany.repair(tv);
    }
}

輸出結(jié)果:

TV proxy find factory for tv.... 
TV factory produce TV...
TV proxy find factory for tv.... 
tv is repair finished...
Process finished with exit code 0

代理對(duì)象不需要實(shí)現(xiàn)該接口,但目標(biāo)對(duì)象必須實(shí)現(xiàn)的接口,否則不能使用動(dòng)態(tài)代理。

動(dòng)態(tài)代理模式,所有函數(shù)調(diào)用最終會(huì)由調(diào)用函數(shù),所以我們可以做一些操作,如日志系統(tǒng)、交易,攔截,權(quán)限控制,等等。

JDK動(dòng)態(tài)代理的最致命的問(wèn)題之一是,它只能代理實(shí)現(xiàn)類實(shí)現(xiàn)一個(gè)接口,代理和代理類只能實(shí)現(xiàn)接口的方法。如果實(shí)現(xiàn)類都有自己的私有方法,但接口不如果是這樣的話,這個(gè)方法不能用于代理調(diào)用。

解決這個(gè)問(wèn)題?我們可以使用CGLIB動(dòng)態(tài)代理機(jī)制。

Cglib代理

靜態(tài)代理和JDK代理需要一個(gè)對(duì)象來(lái)實(shí)現(xiàn)一個(gè)接口。有時(shí)只是一個(gè)單一對(duì)象的代理對(duì)象。在這種情況下,可以使用Cglib代理。

Cglib代理代理,可以被稱為子類構(gòu)造一個(gè)子類對(duì)象在內(nèi)存中實(shí)現(xiàn)擴(kuò)張目標(biāo)對(duì)象的函數(shù)。

劑C不僅想為公司行為,但也想從多個(gè)產(chǎn)品的工廠。

Cglib增強(qiáng)器生成一個(gè)代理類,通過(guò)實(shí)現(xiàn)MethodInterceptor接口,并在截距法實(shí)現(xiàn)的,在這個(gè)過(guò)程中可以添加增強(qiáng)方法和可以使用反射方法或MethodProxy繼承類調(diào)用原方法。

看到B進(jìn)行各種業(yè)務(wù)(接口)的公司,那么這個(gè)時(shí)候代理C發(fā)現(xiàn)了新的商機(jī)。B只能代表一個(gè)特定的公司的產(chǎn)品,我不僅要代表公司的產(chǎn)品,此外,它與不同的工廠,有廣泛的渠道獲得商品,更自由地賺錢。所以使用Cglib。

代碼示例:

public class TVProxyCglib implements MethodInterceptor {
    //給目標(biāo)對(duì)象創(chuàng)建一個(gè)代理對(duì)象
    public Object getProxyInstance(Class c){
        //1.工具類
        Enhancer enhancer = new Enhancer();
        //2.設(shè)置父類
        enhancer.setSuperclass(c);
        //3.設(shè)置回調(diào)函數(shù)
        enhancer.setCallback(this);
        //4.創(chuàng)建子類(代理對(duì)象)
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("TVProxyFactory enhancement.....");
        Object object = methodProxy.invokeSuper(o, objects);
        return object;
    }
}

新代理的工廠

public class TVFactoryB {
    public TV produceTVB() {
        System.out.println("tv factory B producing tv.... ");
        return new TV("華為電視機(jī)", "南京");
    }
    public TV repairB(TV tv) {
        System.out.println("tv B is repair finished.... ");
        return tv;
    }
}

C代理可以直接與該公司合作,或處理工廠。和可以代理任何工廠的產(chǎn)品。

public class TVConsumer {
    public static void main(String[] args) {
        TVCompany tvCompany = (TVCompany) new TVProxyCglib().getProxyInstance(TVFactory.class);
        TV tv = tvCompany.produceTV();
        tvCompany.repair(tv);
        System.out.println("==============================");
        TVFactoryB tvFactoryB = (TVFactoryB) new TVProxyCglib().getProxyInstance(TVFactoryB.class);
        TV tv = tvFactoryB.produceTVB();
        tvFactoryB.repairB(tv);
    }
}

輸出結(jié)果:

TVProxyFactory enhancement.....
TV factory produce TV...
TVProxyFactory enhancement.....
tv is repair finished...
==============================
TVProxyFactory enhancement.....
tv factory B producing tv.... 
TVProxyFactory enhancement.....
tv B is repair finished.... 
Process finished with exit code 0

在SpringAOP使用代理

有兩種實(shí)現(xiàn)AOP在Spring,JDK和Cglib,如下所示:

如果目標(biāo)對(duì)象需要實(shí)現(xiàn)一個(gè)接口,使用JDK代理。

如果目標(biāo)對(duì)象不需要實(shí)現(xiàn)的接口,使用Cglib代理。

總結(jié)

靜態(tài)代理代理類與目標(biāo)類需要實(shí)現(xiàn)接口方法,以便代理可以增強(qiáng)其功能。

JDK動(dòng)態(tài)代理:需要一個(gè)代理類實(shí)現(xiàn)一個(gè)接口,使用代理。newProxyInstance生成代理類方法和實(shí)現(xiàn)InvocationHandler調(diào)用方式來(lái)達(dá)到增強(qiáng)功能。

Cglib動(dòng)態(tài)代理:代理類實(shí)現(xiàn)接口不使用Cblib增強(qiáng)器生成子代理對(duì)象類和實(shí)現(xiàn)MethodInterceptor攔截方法,這種方法可以達(dá)到增強(qiáng)功能。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

  • 全國(guó)校區(qū) 2025-05-15 搶座中
  • 全國(guó)校區(qū) 2025-06-05 搶座中
  • 全國(guó)校區(qū) 2025-06-26 搶座中
免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 精品国产一区二区三区国产馆 | 欧美日本韩国国产 | 水果视频在线观看 | 日韩色天使综合色视频 | 天天色天天拍 | 日韩中文字幕网 | 国产第一页亚洲 | 黄色大片免费看 | 亚洲国产成人精品91久久久 | 又爽又黄又无遮挡网站 | 一级成人a做片免费 | 欧美福利片在线观看 | 国产精品一国产精品免费 | 最近的中文字幕大全免费8 最近的中文字幕2019更新 | 国产黄色一级 | 日韩在线视频网站 | 日本一区二区中文字幕 | 久久精品网站免费观看 | 免费人成在线观看视频不卡 | 日韩欧美视频免费观看 | 一级有奶水毛片免费看 | 免费亚洲视频在线观看 | 三级日韩 | 免费吃奶摸下激烈视频青青网 | 500福利笫一精品导航 | 欧美亚洲国产精品久久 | 欧美成人午夜影院 | 亚洲男人天堂网站 | 在线观看免费成人 | 亚洲视频2 | 伊人99在线| 欧美在线黄色 | 欧美 日韩 高清 | 91久久精一区二区三区大全 | 日韩黄色一级视频 | 真人一级一级特黄高清毛片 | 麻豆国产高清在线播放 | 色综合成人网 | 奇米影视亚洲色图 | 在线欧美不卡 | 日本高清va不卡视频在线观看 |