亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

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

靜態(tài)代理

實(shí)現(xiàn)簡述

本質(zhì)上是一接口一代理,對該接口的所有實(shí)現(xiàn)類進(jìn)行"增強(qiáng)"(額外)操作:

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

創(chuàng)建human接口

public interface Human {
    public void sex();
}

創(chuàng)建接口實(shí)現(xiàn)類

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)建針對接口實(shí)現(xiàn)增強(qiá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 ");
    }
}

代理實(shí)現(xiàn)效果

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)代理

實(shí)現(xiàn)簡述

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

動態(tài)代理類主要實(shí)現(xiàn)InvocationHandler這個(gè)接口,接口實(shí)現(xiàn)invoke方法來實(shí)現(xiàn)增強(qiáng)操作。并通過一個(gè)自定義的方法來創(chuàng)建和綁定動態(tài)代理類和入?yún)ⅲㄏ蛏限D(zhuǎn)型為obj的實(shí)現(xiàn)類對象),從而實(shí)現(xiàn)實(shí)現(xiàn)類對象方法的增強(qiáng)操作。

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

這里我們有兩個(gè)疑問:

1、如何實(shí)現(xiàn)增強(qiáng)的invoke方法;——通過java.lang.reflect.Proxy.newProxyInstance方法中復(fù)原向上轉(zhuǎn)型的obj對象為原對象(具體實(shí)現(xiàn)類對象),并綁定增強(qiáng)的invoke方法。

2、代理對象如何復(fù)現(xiàn)對象方法; ——利用向上轉(zhuǎn)型的復(fù)原不變性。

要點(diǎn):向上轉(zhuǎn)型

向上轉(zhuǎn)型:子類實(shí)例賦值給父類引用。 無法調(diào)用子類拓展方法,但是她的實(shí)現(xiàn)確確實(shí)實(shí)存在:

        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接口,兩個(gè)接口。

public interface YoungMan {
    public void nickName();
}

創(chuàng)建兩個(gè)接口實(shí)現(xiàn)類

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)代理實(shí)例對象

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

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

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

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

invoke方法中的args為方法傳入的參數(shù)們;

public class GodForYoungProxy implements InvocationHandler {
    private Object godForYoungProxy;
    //參數(shù)為Object設(shè)計(jì)一個(gè)向上轉(zhuǎn)型
    public Object newProxyInstance(Object godForYoungProxy) {
        this.godForYoungProxy = godForYoungProxy;
        //this指的是GodForYoungProxy這個(gè)InvocationHandler實(shí)現(xiàn)類
        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;
    }
}

代理實(shí)現(xiàn)效果

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();
        //向上轉(zhuǎn)型測試
//        Object obj = new Girl();
//        Girl girl = (Girl) obj;
//        System.err.println(obj.getClass().getName());
//        System.err.println(obj.getClass().getInterfaces().length);
//        girl.nickName();
    }
}

在這里插入圖片描述

代理生成對象中的obj向上轉(zhuǎn)型對象的.getClass().getName()打印:

在這里插入圖片描述

要點(diǎn):InvocationHandler補(bǔ)充

結(jié)合創(chuàng)建動態(tài)代理實(shí)例對象目錄內(nèi)容補(bǔ)充說明如下:官網(wǎng)的Proxy.newProxyInstance中的入?yún)⒄f明

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 =>將方法調(diào)用分派到的調(diào)用處理程序

同樣的上述代碼實(shí)現(xiàn)效果,我們將實(shí)現(xiàn)的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ā)現(xiàn)少了實(shí)際的sex和nickName方法的輸出內(nèi)容,因?yàn)闆]有實(shí)現(xiàn)對應(yīng)調(diào)用方法:

在這里插入圖片描述

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

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

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

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

2、代理模式:強(qiáng)調(diào)對對象的訪問控制,方法的使用都是通過反射實(shí)現(xiàn);代理模式則是強(qiáng)調(diào)功能的增加,相當(dāng)于在原基礎(chǔ)的被修飾者上不斷套娃。

總結(jié)

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

相關(guān)文章

  • SpringBoot統(tǒng)計(jì)接口調(diào)用耗時(shí)的三種方式

    SpringBoot統(tǒng)計(jì)接口調(diào)用耗時(shí)的三種方式

    在實(shí)際開發(fā)中,了解項(xiàng)目中接口的響應(yīng)時(shí)間是必不可少的事情,SpringBoot 項(xiàng)目支持監(jiān)聽接口的功能也不止一個(gè),接下來我們分別以 AOP、ApplicationListener、Tomcat 三個(gè)方面去實(shí)現(xiàn)三種不同的監(jiān)聽接口響應(yīng)時(shí)間的操作,需要的朋友可以參考下
    2024-06-06
  • Java類加載器層次結(jié)構(gòu)原理解析

    Java類加載器層次結(jié)構(gòu)原理解析

    這篇文章主要介紹了Java類加載器層次結(jié)構(gòu)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 阿里云主機(jī)上安裝jdk 某庫出現(xiàn)問題的解決方法

    阿里云主機(jī)上安裝jdk 某庫出現(xiàn)問題的解決方法

    今天安裝jdk到阿里云服務(wù)上,首先看下阿里云是32位還是64位的,如果是32位下載32位的包,如果是64位的下載64位的包,下面與大家分享下安裝過程中遇到問題的解決方法
    2013-06-06
  • springboot+log4j.yml配置日志文件的方法

    springboot+log4j.yml配置日志文件的方法

    這篇文章主要介紹了springboot+log4j.yml配置日志文件的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Java集合-HashMap

    Java集合-HashMap

    這篇文章主要介紹了Java集合HashMap,也叫散列表,是一種非常重要的數(shù)據(jù)結(jié)構(gòu),應(yīng)用場景及其豐富,許多緩存技術(shù)(比如memcached)的核心其實(shí)就是在內(nèi)存中維護(hù)一張大的哈希表,下面來看看文章的具體內(nèi)容吧,需要的小伙伴也可參考一下
    2022-01-01
  • Java中的Redis是什么意思

    Java中的Redis是什么意思

    Redis是一個(gè)非常強(qiáng)大的工具,它可以用來實(shí)現(xiàn)很多有趣的應(yīng)用,還可以使用Redis來實(shí)現(xiàn)分布式鎖,這樣你就可以在多線程或多進(jìn)程的環(huán)境下同步代碼,這篇文章主要介紹了Java中的Redis是什么意思,需要的朋友可以參考下
    2023-08-08
  • 一文詳解gRPC快速整合SpringCloud

    一文詳解gRPC快速整合SpringCloud

    這篇文章主要為大家介紹gRPC快速整合SpringCloud的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Spring Boot2.0實(shí)現(xiàn)靜態(tài)資源版本控制詳解

    Spring Boot2.0實(shí)現(xiàn)靜態(tài)資源版本控制詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot2.0實(shí)現(xiàn)靜態(tài)資源版本控制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 詳解Spring Boot中Controller用法

    詳解Spring Boot中Controller用法

    Controller是SpringBoot里最基本的組件,他的作用是把用戶提交來的請求通過對URL的匹配,分配個(gè)不同的接收器,再進(jìn)行處理,然后向用戶返回結(jié)果。下面通過本文給大家介紹Spring Boot中Controller用法,需要的朋友參考下
    2017-05-05
  • Java內(nèi)部類和異常類的概念以及使用

    Java內(nèi)部類和異常類的概念以及使用

    這篇文章主要介紹了Java內(nèi)部類和異常類的概念以及使用,文中有非常詳細(xì)的代碼以及注釋,適合正在學(xué)習(xí)java基礎(chǔ)的同學(xué)們使用,需要的朋友可以參考下
    2021-04-04

最新評論