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

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

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

更新時間:2022-04-20 10:43:05 來源:動力節(jié)點 瀏覽976次

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

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

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

代理模型有三個角色:

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

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

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

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

靜態(tài)代理

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

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

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

代碼示例:

電視:

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();
    }
}

消費者獲得商品通過代理(代理)的使用:

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)點:靜態(tài)代理模式實現(xiàn)的功能擴(kuò)張目標(biāo)對象不改變目標(biāo)對象。

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

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

動態(tài)代理

動態(tài)代理有以下特點:

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

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

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

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

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

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

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

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

代碼示例:

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

工廠也開始維護(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方法生成一個代理對象在調(diào)用方法,實現(xiàn)InvocationHandler反映在代理類的方法調(diào)用通過調(diào)用方法,并提供一個增強(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;
            }
        });
    }
}

購買和修理這兩個服務(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

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

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

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

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

Cglib代理

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

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

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

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

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

代碼示例:

public class TVProxyCglib implements MethodInterceptor {
    //給目標(biāo)對象創(chuàng)建一個代理對象
    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)建子類(代理對象)
        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使用代理

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

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

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

總結(jié)

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

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

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

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 亚洲美女aⅴ久久久91 | 青草视频网站在线观看 | 免费观看三级毛片 | 成人激情视频在线 | 伊人热热久久原色播放www | 日日摸夜夜添夜夜添成人 | 77久久| 日韩高清性爽一级毛片免费 | 国产免费高清在线精品一区 | 99视频在线精品 | 亚洲激情视频在线播放 | 中文字幕在线看视频一区二区三区 | 亚洲国产aaa毛片无费看 | 色播在线永久免费视频网站 | 男女一级爽爽快视频 | 男人爱看的视频网站免费 | 欧美一区二区三区免费看 | 欧美xxx视频在线观看 | 午夜影院色 | 亚洲成人网在线 | 我想看黄色毛片 | 日韩伦理片在线观看光棍影院 | 欧美一级h | 黄网站色成年片在线观看 | 色综合狠狠操 | 老司机午夜在线 | 免费看欧美一级特黄α大片 | 可以免费看毛片的网站 | 成人污视频在线观看 | 在线成人爽a毛片免费软件 在线成人影片 | 亚洲三级在线免费观看 | 国产成人精品视频频 | 国产凹凸一区在线观看视频 | 亚欧美图片自偷自拍另类 | 女性爽爽影院免费观看麻豆 | 韩国理伦片a级在线观看 | 亚洲一区在线视频 | 全免费午夜真人毛片视频 | 欧美日韩一区二区三区在线观看 | 成人精品福利 | 另类色综合 |