最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

代理模式:JAVA靜態(tài)代理和動態(tài)代理的實例和實現詳解

 更新時間:2021年08月24日 10:17:37   作者:長臂人猿  
這篇文章主要給大家介紹了關于Java靜態(tài)代理和動態(tài)代理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

代理模式,我們這里結合JAVA的靜態(tài)代理和動態(tài)代理來說明,類比Spring AOP面向切面編程:增強消息,也是代理模式。

而我們的靜態(tài)代理和動態(tài)代理,與(service)接口和(serviceImpl)接口實現類有什么區(qū)別呢?靜態(tài)代理的概念與其在理解上類似,可以說靜態(tài)代理是實現類的增強消息。而且,靜態(tài)代理針對的是所以實現接口的實現類(通過向上轉型實現)。

靜態(tài)代理

實現簡述

本質上是一接口一代理,對該接口的所有實現類進行"增強"(額外)操作:

如下例:human接口有兩個實現類:man和woman,我們需要在每個human接口被實現的時候說他是god創(chuàng)造的(增強操作)。那么我們針對human接口手動實現一個GodProxy靜態(tài)代理類。那么我們通過這個代理執(zhí)行human接口的實現對象的方法時就可以引入增強操作。

創(chuàng)建human接口

public interface Human {
    public void sex();
}

創(chuàng)建接口實現類

public class Man implements Human{
    @Override
    public void sex() {
        System.out.println( "this is Man" );
    }
}
public class Women implements Human{
    @Override
    public void sex() {
        System.out.println( "this is Women" );
    }
}

創(chuàng)建針對接口實現增強操作的代理

public class GodProxy implements Human{
    Human huamnGenarator;
    public GodProxy(Human huamnGenarator){
        this.huamnGenarator = huamnGenarator;
    }
    @Override
    public void sex() {
        System.out.println( "God begin to make human" );
        huamnGenarator.sex();
        System.out.println(" End of work ");
    }
}

代理實現效果

public class 靜態(tài)代理 {
    public static void main(String[] args) {
        GodProxy proxy_1 = new GodProxy(new Man());
        GodProxy proxy_2 = new GodProxy(new Women());
        proxy_1.sex();
        System.out.println("\n\n");
        proxy_2.sex();
    }
}

在這里插入圖片描述

動態(tài)代理

實現簡述

相對與靜態(tài)代理,一個代理類proxy只能針對一個接口實現操作,眾所周知類可以實現多個接口,那能不能對所有的實現類的接口實現增強操作呢?可以的,我們需要通過反射的方式,通過向上轉型使得傳入參數為Object對象,但是Object里面的getClass方法獲取Class對象,實際上是實現類的Class(由Java的向上轉型特性可知)。 獲取實現類對象的class對象且獲得其實現的接口數組。我們可以達到這個目的:這就是動態(tài)代理:對多個接口實現靜態(tài)代理。

動態(tài)代理類主要實現InvocationHandler這個接口,接口實現invoke方法來實現增強操作。并通過一個自定義的方法來創(chuàng)建和綁定動態(tài)代理類和入參(向上轉型為obj的實現類對象),從而實現實現類對象方法的增強操作。

即我們通過動態(tài)代理傳入實例類對象,在自己寫的newProxyInstance方法中通過Proxy類的newProxyInstance方法代理生成一個新的實例類對象,這個新的對象不僅包含所有的入參實力類對象信息,且在通過代理類生成新的實例類對象過程中注入了invoke方法(我們實現InvocationHandler接口的核心方法)的邏輯。

這里我們有兩個疑問:

1、如何實現增強的invoke方法;——通過java.lang.reflect.Proxy.newProxyInstance方法中復原向上轉型的obj對象為原對象(具體實現類對象),并綁定增強的invoke方法。

2、代理對象如何復現對象方法; ——利用向上轉型的復原不變性。

要點:向上轉型

向上轉型:子類實例賦值給父類引用。 無法調用子類拓展方法,但是她的實現確確實實存在:

        Object obj = new Girl();
        Girl girl = (Girl) obj;
        System.err.println(obj.getClass().getName());
        System.err.println(obj.getClass().getInterfaces().length);
        girl.nickName();

輸出:

src.代理模式.Girl
2

少女

創(chuàng)建YoungMan接口

這里還將用到Human接口,兩個接口。

public interface YoungMan {
    public void nickName();
}

創(chuàng)建兩個接口實現類

public class Boy implements Human,YoungMan{
    @Override
    public void sex() {
        System.out.println( "this is Man" );
    }
    @Override
    public void nickName() {
        System.out.println( "少年" );
    }
}

public class Girl implements Human,YoungMan{
    @Override
    public void sex() {
        System.out.println( "this is Women" );
    }
    @Override
    public void nickName() {
        System.out.println( "少女" );
    }
}

創(chuàng)建動態(tài)代理實例對象

這里我們主要通過Proxy.newProxyInstance方法創(chuàng)建一個代理類,傳參:

   public static Object newProxyInstance(ClassLoader loader, 
                                            Class<?>[] interfaces, 
                                            InvocationHandler h)

類加載器:指定代理類由哪個classloader加載;代理類需要代理實現的接口方法;InvocationHandler對象:表示的是當動態(tài)代理對象調用方法的時候實際執(zhí)行的會是該InvocationHandler對象上的invoke方法(即增強方法)。在invoke方法中通過反射方法名稱去執(zhí)行實際要執(zhí)行的方法和增強操作。(實例說明可以看文末補充)

注意返回的這里自定義的newProxyInstance是Object。

invoke方法中的args為方法傳入的參數們;

public class GodForYoungProxy implements InvocationHandler {
    private Object godForYoungProxy;
    //參數為Object設計一個向上轉型
    public Object newProxyInstance(Object godForYoungProxy) {
        this.godForYoungProxy = godForYoungProxy;
        //this指的是GodForYoungProxy這個InvocationHandler實現類
        System.err.println( godForYoungProxy.getClass().getName() );
        return Proxy.newProxyInstance(godForYoungProxy.getClass().getClassLoader(), godForYoungProxy.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(" God for Young begin to work ... ");
        proxy = method.invoke(godForYoungProxy, args);
        System.out.println(" End of work ");
        return proxy;
    }
}

代理實現效果

public class 動態(tài)代理 {
    public static void main(String[] args) {
        GodForYoungProxy godForYoungProxy = new GodForYoungProxy();
        Human human = (Human) godForYoungProxy.newProxyInstance(new Boy());
        YoungMan youngMan = (YoungMan) godForYoungProxy.newProxyInstance(new Boy());
        human.sex();
        youngMan.nickName();
        //向上轉型測試
//        Object obj = new Girl();
//        Girl girl = (Girl) obj;
//        System.err.println(obj.getClass().getName());
//        System.err.println(obj.getClass().getInterfaces().length);
//        girl.nickName();
    }
}

在這里插入圖片描述

代理生成對象中的obj向上轉型對象的.getClass().getName()打?。?/p>

在這里插入圖片描述

要點:InvocationHandler補充

結合創(chuàng)建動態(tài)代理實例對象目錄內容補充說明如下:官網的Proxy.newProxyInstance中的入參說明

loader – the class loader to define the proxy class
interfaces – the list of interfaces for the proxy class to implement
h – the invocation handler to dispatch method invocations to =>將方法調用分派到的調用處理程序

同樣的上述代碼實現效果,我們將實現的GodForYoungProxy implements InvocationHandler中的invoke方法注釋一行:

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(" God for Young begin to work ... ");
       // proxy = method.invoke(godForYoungProxy, args);
        System.out.println(" End of work ");
        return proxy;
    }

明顯的,我們發(fā)現少了實際的sex和nickName方法的輸出內容,因為沒有實現對應調用方法:

在這里插入圖片描述

通過這樣的特性,其實我們在invoke方法里面擁有很強的操作性,比如說讓指定方法執(zhí)行,對不同方法執(zhí)行不同策略等。

代理模式和修飾模式的區(qū)別

代理模式和裝飾者模式很相似,但是他們的區(qū)別在于:

1、代理模式是在類編譯的時候,增強方法就已經確定的,有些動態(tài)代理不支持多層嵌套;裝飾者則可以不斷遞歸被構造裝飾;

2、代理模式:強調對對象的訪問控制,方法的使用都是通過反射實現;代理模式則是強調功能的增加,相當于在原基礎的被修飾者上不斷套娃。

總結

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!

相關文章

  • spring @Lazy延遲注入的邏輯實現

    spring @Lazy延遲注入的邏輯實現

    有時候我們會在屬性注入的時候添加@Lazy注解實現延遲注入,今天咱們通過閱讀源碼來分析下原因,感興趣的可以了解一下
    2021-08-08
  • springboot serverEndpoint導致@resource注解不生效

    springboot serverEndpoint導致@resource注解不生效

    在SpringBoot中,@Resource注解用于注入依賴,本文主要介紹了springboot serverEndpoint導致@resource注解不生效,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • java實現短信通信的完整教程

    java實現短信通信的完整教程

    這篇文章主要為大家詳細介紹了java實現短信通信的完整教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java8新特性Optional常用方法

    Java8新特性Optional常用方法

    optional類是Java8新增加的一個對象容器,主要的功能有對象的創(chuàng)建、獲取、判斷、過濾,映射等,下面這篇文章主要給大家介紹了關于Java8新特性Optional常用方法的相關資料,需要的朋友可以參考下
    2024-02-02
  • java實現順序結構線性列表的函數代碼

    java實現順序結構線性列表的函數代碼

    java實現順序結構線性列表的函數代碼。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • 解決idea web工程修改js文件之后不變化的問題

    解決idea web工程修改js文件之后不變化的問題

    這篇文章主要介紹了解決idea web工程修改js文件之后不變化的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Java如何執(zhí)行cmd命令

    Java如何執(zhí)行cmd命令

    這篇文章主要介紹了Java如何執(zhí)行cmd命令問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 如何解決Maven打包時每次都出現Download maven-metadata.xml卡住問題

    如何解決Maven打包時每次都出現Download maven-metadata.xml卡住問題

    這篇文章主要介紹了如何解決Maven打包時每次都出現Download maven-metadata.xml卡住問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java ExecutorService CompletionService線程池區(qū)別與選擇

    java ExecutorService CompletionService線程池區(qū)別與選擇

    這篇文章主要為大家介紹了java ExecutorService CompletionService線程池區(qū)別與選擇使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • java實現簡單的汽車租賃系統(tǒng)

    java實現簡單的汽車租賃系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現簡單的汽車租賃系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論

黄山市| 广灵县| 漳州市| 达州市| 家居| 芜湖县| 仲巴县| 乌兰察布市| 伊春市| 河北区| 新河县| 深水埗区| 玉林市| 武冈市| 凤阳县| 屯留县| 嘉黎县| 清远市| 红原县| 盐边县| 龙泉市| 伊宁县| 蒲江县| 清流县| 隆化县| 宣恩县| 宁武县| 九龙坡区| 资阳市| 威信县| 玛纳斯县| 金堂县| 稷山县| 射洪县| 石景山区| 宁明县| 海城市| 汉川市| 曲周县| 海南省| 和平区|