欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java代理模式(jdk proxy)

 更新時(shí)間:2021年07月09日 11:48:35   作者:程序dunk  
代理(Proxy)是一種設(shè)計(jì)模式,提供了對(duì)目標(biāo)對(duì)象另外的訪問(wèn)方式;這篇文章主要介紹了Java 中的三種代理模式,需要的朋友可以參考下,希望能幫助到你

什么是代理

舉個(gè)栗子

比如有一家美國(guó)的大學(xué),可以對(duì)全世界招生。但是對(duì)于家長(zhǎng)來(lái)說(shuō),家長(zhǎng)不能直接自己去找學(xué)校,家長(zhǎng)沒(méi)有能力去直接訪問(wèn)學(xué)校,或者說(shuō),美國(guó)學(xué)校不接受個(gè)人來(lái)訪,那么此時(shí)就需要一個(gè)留學(xué)中介來(lái)幫助這家美國(guó)學(xué)校招

生,中介就是學(xué)校的代理。中介和學(xué)校要做的事情是一致:招生。對(duì)于家長(zhǎng)來(lái)說(shuō),學(xué)校就是目標(biāo),留學(xué)中介就是代理。日常生活中,有許多代理的例子,比如:代購(gòu),房產(chǎn)中介,各種中介,換ip,商家廠家和買家。在開(kāi)發(fā)中

也有同樣的情況,比如,你有a類, 本來(lái)是調(diào)用c類的方法, 完成某個(gè)功能。 但是c不讓a調(diào)用。 a -----不能調(diào)用 c的方法。在a 和 c 直接 創(chuàng)建一個(gè) b 代理, c讓b訪問(wèn)。 a --訪問(wèn)b---訪問(wèn)c。

原來(lái)的訪問(wèn)關(guān)系

通過(guò)代理的訪問(wèn)關(guān)系

什么是代理模式

百度百科

代理模式是指,為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶類和目標(biāo)對(duì)象之間起到中介的作用。

換句話說(shuō),使用代理對(duì)象,是為了在不修改目標(biāo)對(duì)象的基礎(chǔ)上,增強(qiáng)主業(yè)務(wù)邏輯??蛻纛愓嬲南胍L問(wèn)的對(duì)象是目標(biāo)對(duì)象,但客戶類真正可以訪問(wèn)的對(duì)象是代理對(duì)象??蛻纛悓?duì)目標(biāo)對(duì)象的訪問(wèn)是通過(guò)訪問(wèn)代理對(duì)象來(lái)實(shí)現(xiàn)

的。當(dāng)然,代理類與目標(biāo)類要實(shí)現(xiàn)同一個(gè)接口。

實(shí)現(xiàn)代理的方式

靜態(tài)代理

靜態(tài)代理是指,代理類在程序運(yùn)行前就已經(jīng)定義好.java 源文件,其與目標(biāo)類的關(guān)系在程序運(yùn)行前就已經(jīng)確立。在程序運(yùn)行前代理類已經(jīng)編譯為.class 文件。

舉一個(gè)靜態(tài)代理的例子

需求:用戶需要購(gòu)買 u 盤(pán),u 盤(pán)廠家不單獨(dú)接待零散購(gòu)買,廠家規(guī)定一次最少購(gòu)買 1000個(gè)以上,用戶可以通過(guò)淘寶的代理商,或者微商哪里進(jìn)行購(gòu)買。淘寶上的商品,微商都是 u 盤(pán)工廠的代理商, 他們代理對(duì) u 盤(pán)的銷售業(yè)

務(wù)。用戶購(gòu)買-------代理商(淘寶,微商)----- u 盤(pán)廠家(金士頓,閃迪等不同的廠家)

1、定義業(yè)務(wù)接口

定義業(yè)務(wù)接口UsbSell(目標(biāo)接口),其中含有抽象方法sell(int amout);sell是目標(biāo)方法

public interface UsbSell {
    /**
     * 表示功能的,廠家和商家都要完成的功能
     * @param amount
     * @return
     */
    float sellUsb(int amount);
}

2、定義接口的實(shí)現(xiàn)類

目標(biāo)類UsbKingFactory金士頓U盤(pán),該類實(shí)現(xiàn)了接口

import school.xauat.service.UsbSell;
public class UsbKingFactory  implements UsbSell {
    @Override
    /**
     * 定義金士頓廠家的銷售價(jià)格
     */
    public float sellUsb(int account) {
        return 75.0f;
    }
}

3、定義代理

TaoBao就是一個(gè)代理類,代理廠家銷售U盤(pán)

import school.xauat.factory.UsbKingFactory;
import school.xauat.service.UsbSell;
public class Taobao implements UsbSell {
    //聲明 商家代理的廠家具體是哪一家
    private UsbSell factory=new UsbKingFactory();
    @Override
    /**
     * 實(shí)現(xiàn)銷售U盤(pán)的功能
     */
    public float sellUsb(int account) {
        float price=factory.sellUsb(account);
        //代理增強(qiáng)功能
        price+=25;
        return price;
    }
}

WeiShang也是一個(gè)代理類代理廠家銷售U盤(pán)

import school.xauat.factory.UsbKingFactory;
import school.xauat.service.UsbSell;
public class Weishang implements UsbSell {
    //聲明 商家代理的廠家具體是哪一家
    private UsbSell factory=new UsbKingFactory();
    @Override
    public float sellUsb(int amount) {
        float price=factory.sellUsb(amount);
        //代理增強(qiáng)功能
        price+=15;
        return price;
    }
}

4、客戶端調(diào)用者,購(gòu)買商品類

客戶端可以通過(guò)Taobao和WeiShang兩個(gè)代理來(lái)購(gòu)買U盤(pán)

import school.xauat.business.Taobao;
import school.xauat.business.Weishang;
public class ShopMain {
    public static void main(String[] args) {
        Taobao taoBao=new Taobao();
        float price=taoBao.sellUsb(1);
        System.out.println(price);
        Weishang weishang=new Weishang();
        float price2=weishang.sellUsb(1);
        System.out.println(price2);
    }
}

根據(jù)以上過(guò)程,分析靜態(tài)代理的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,易于理解

缺點(diǎn):

代碼復(fù)雜,難于管理

代理類和目標(biāo)類實(shí)現(xiàn)了相同的接口,每個(gè)代理都需要實(shí)現(xiàn)目標(biāo)類的方法,這樣就出現(xiàn)了大量的代碼重復(fù)。如果接口增加一個(gè)方法,除了所有目標(biāo)類需要實(shí)現(xiàn)這個(gè)方法外,所有代理類也需要實(shí)現(xiàn)此方法。增加了代碼維護(hù)的復(fù)雜度。

代理類依賴目標(biāo)類,代理類過(guò)多

代理類只服務(wù)于一種類型的目標(biāo)類,如果要服務(wù)多個(gè)類型。勢(shì)必要為每一種目標(biāo)類都進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時(shí)就無(wú)法勝任了,代理類數(shù)量過(guò)多。

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

動(dòng)態(tài)代理是指代理類對(duì)象在程序運(yùn)行時(shí)由 JVM 根據(jù)反射機(jī)制動(dòng)態(tài)生成的。動(dòng)態(tài)代理不需要定義代理類的.java 源文件。

動(dòng)態(tài)代理其實(shí)就是 jdk 運(yùn)行期間,動(dòng)態(tài)創(chuàng)建 class 字節(jié)碼并加載到 JVM。

動(dòng)態(tài)代理的實(shí)現(xiàn)方式常用的有兩種:使用 JDK 動(dòng)態(tài)代理(這里主要講),與通過(guò) CGLIB 動(dòng)態(tài)代理。

CGLIB代理

CGLIB(Code Generation Library)是一個(gè)開(kāi)源項(xiàng)目。是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的 Code 生成類庫(kù),它可以在運(yùn)行期擴(kuò)展 Java 類與實(shí)現(xiàn) Java 接口。它廣泛的被許多 AOP 的框架使用,例如 Spring AOP。使用 JDK 的

Proxy 實(shí)現(xiàn)代理,要求目標(biāo)類與代理類實(shí)現(xiàn)相同的接口。若目標(biāo)類不存在接口,則無(wú)法使用該方式實(shí)現(xiàn)。但對(duì)于無(wú)接口的類,要為其創(chuàng)建動(dòng)態(tài)代理,就要使用 CGLIB 來(lái)實(shí)現(xiàn)。CGLIB 代理的生成原理是生成目標(biāo)類的子類,而

子類是增強(qiáng)過(guò)的,這個(gè)子類對(duì)象就是代理對(duì)象。所以,使用CGLIB 生成動(dòng)態(tài)代理,要求目標(biāo)類必須能夠被繼承,即不能是 final 的類。cglib 經(jīng)常被應(yīng)用在框架中,例如 Spring ,Hibernate 等。Cglib 的代理效率高于 Jdk。對(duì)

于 cglib 一般的開(kāi)發(fā)中并不使用。做了一個(gè)了解就可以。

JDK代理

jdk 動(dòng)態(tài)代理是基于 Java 的反射機(jī)制實(shí)現(xiàn)的。使用 jdk 中接口和類實(shí)現(xiàn)代理對(duì)象的動(dòng)態(tài)創(chuàng) 建。 Jdk 的動(dòng)態(tài)要求目標(biāo)對(duì)象必須實(shí)現(xiàn)接口,這是 java 設(shè)計(jì)上的要求。 從 jdk1.3 以來(lái),java 語(yǔ)言通過(guò) java.lang.reflect 包提供三個(gè)類

支持代理模式 Proxy, Method InovcationHandler

InvocationHandler接口

InvocationHandler 接口叫做調(diào)用處理器,負(fù)責(zé)完調(diào)用目標(biāo)方法,并增強(qiáng)功能。通 過(guò) 代 理 對(duì) 象 執(zhí) 行 目 標(biāo) 接 口 中 的 方 法 , 會(huì) 把 方 法 的 調(diào) 用 分 派 給 調(diào) 用 處 理 器(InvocationHandler)的實(shí)現(xiàn)類,執(zhí)行實(shí)現(xiàn)類中的 i

nvoke()方法,我們需要把功能代理寫(xiě)在 invoke()方法中 。

在 invoke 方法中可以截取對(duì)目標(biāo)方法的調(diào)用。在這里進(jìn)行功能增強(qiáng)。Java 的動(dòng)態(tài)代理是建立在反射機(jī)制之上的。實(shí)現(xiàn)了 InvocationHandler 接口的類用于加強(qiáng)目標(biāo)類的主業(yè)務(wù)邏輯。這個(gè)接口中有一個(gè)方法 invoke(),具體加

強(qiáng)的代碼邏輯就是定義在該方法中的。通過(guò)代理對(duì)象執(zhí)行接口中的方法時(shí),會(huì)自動(dòng)調(diào)用 invoke()方法。

invoke()方法的介紹如下:

public Object invoke ( Object proxy, Method method, Object[] args)

proxy:代表生成的代理對(duì)象

method:代表目標(biāo)方法

args:代表目標(biāo)方法的參數(shù)

第一個(gè)參數(shù) proxy 是 jdk 在運(yùn)行時(shí)賦值的,在方法中直接使用,第二個(gè)參數(shù)后面介紹,第三個(gè)參數(shù)是方法執(zhí)行的參數(shù), 這三個(gè)參數(shù)都是 jdk 運(yùn)行時(shí)賦值的,無(wú)需程序員給出。

Method類

invoke()方法的第二個(gè)參數(shù)為 Method 類對(duì)象,該類有一個(gè)方法也叫 invoke(),可以調(diào)用目標(biāo)方法。這兩個(gè) invoke()方法,雖然同名,但無(wú)關(guān)。

public Object invoke ( Object obj, Object... args)

obj:表示目標(biāo)對(duì)象

args:表示目標(biāo)方法參數(shù),就是其上一層 invoke 方法的第三個(gè)參數(shù)

該方法的作用是:調(diào)用執(zhí)行 obj 對(duì)象所屬類的方法,這個(gè)方法由其調(diào)用者 Method 對(duì)象確定。

在代碼中,一般的寫(xiě)法為

method.invoke(target, args);

其中,method 為上一層 invoke 方法的第二個(gè)參數(shù)。這樣,即可調(diào)用了目標(biāo)類的目標(biāo)方法。

Proxy類

通 過(guò) JDK 的 java.lang.reflect.Proxy 類 實(shí) 現(xiàn) 動(dòng) 態(tài) 代 理 , 會(huì) 使 用 其 靜 態(tài) 方 法newProxyInstance(),依據(jù)目標(biāo)對(duì)象、業(yè)務(wù)接口及調(diào)用處理器三者,自動(dòng)生成一個(gè)動(dòng)態(tài)代理對(duì)象。

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

loader:目標(biāo)類的類加載器,通過(guò)目標(biāo)對(duì)象的反射可獲取

interfaces:目標(biāo)類實(shí)現(xiàn)的接口數(shù)組,通過(guò)目標(biāo)對(duì)象的反射可獲取

handler:調(diào)用處理器。

jdk動(dòng)態(tài)代理的實(shí)現(xiàn)步驟

jdk 動(dòng)態(tài)代理是代理模式的一種實(shí)現(xiàn)方式,其只能代理接口。

實(shí)現(xiàn)步驟

1、新建一個(gè)接口,作為目標(biāo)接口

2、為接口創(chuàng)建一個(gè)實(shí)現(xiàn)類,是目標(biāo)類

3、創(chuàng)建類實(shí)現(xiàn) java.lang.reflect.InvocationHandler 接口,調(diào)用目標(biāo)方法并增加其他功能代碼

4、創(chuàng)建動(dòng)態(tài)代理對(duì)象,使用 Proxy.newProxyInstance()方法,并把返回值強(qiáng)制轉(zhuǎn)為接口類型。

舉例

1、創(chuàng)建目標(biāo)接口,定義目標(biāo)接口功能

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

以上兩步同靜態(tài)代理

3、創(chuàng)建InvocationHandler接口的實(shí)現(xiàn)類,調(diào)用目標(biāo)方法和增加其他代碼功能

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MySellHandler implements InvocationHandler {
    //目標(biāo)對(duì)象
    private Object target=null;
    public MySellHandler(Object target){
        this.target=target;
    }
    @Override
    /**
     * 實(shí)現(xiàn)InvocationHandler接口的實(shí)現(xiàn)類,在invoke方法中完成代理類的功能
     *      -調(diào)用目標(biāo)方法
     *      -功能增強(qiáng)
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result=null;
        result=method.invoke(target,args);

        //功能增強(qiáng)
        //這里為了簡(jiǎn)化,我們將功能增強(qiáng)定義為加價(jià)25元
        if (result!=null){
            float price=(float)result;
            price=price+25;
            result=price;
        }
        return result;
    }
}

這里的target對(duì)象相當(dāng)于靜態(tài)代理中的TaoBao和WeiShang

4、模擬客戶購(gòu)買U盤(pán),使用proxy.newProxyInstance創(chuàng)建Proxy代理對(duì)象并且使返回值為目標(biāo)接口類型

import school.xauat.factory.UsbKingFactory;
import school.xauat.handler.MySellHandler;
import school.xauat.service.UsbSell;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainShop {
    public static void main(String[] args) throws Exception {
        //創(chuàng)建目標(biāo)對(duì)象
        Class c=UsbKingFactory.class;
        Object obj=c.newInstance();
        //獲得目標(biāo)類的類加載器
        ClassLoader loader =UsbKingFactory.class.getClassLoader();
        //獲取目標(biāo)類實(shí)現(xiàn)的接口數(shù)組
        Class<?>[]interfaces=obj.getClass().getInterfaces();
        //創(chuàng)建InvocationHandler對(duì)象
        InvocationHandler handler=new MySellHandler(obj);
        //創(chuàng)建代理對(duì)象
        UsbSell proxy=(UsbSell) Proxy.newProxyInstance(loader,interfaces,handler);
        //通過(guò)這個(gè)代理執(zhí)行方法
        float price=proxy.sell(1);
        System.out.println(price);
    }
}

靜態(tài)代理

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

UML圖

總結(jié)

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

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)動(dòng)態(tài)插拔的AOP的完整案例

    SpringBoot實(shí)現(xiàn)動(dòng)態(tài)插拔的AOP的完整案例

    在現(xiàn)代軟件開(kāi)發(fā)中,面向切面編程(AOP) 是一種非常重要的技術(shù),能夠有效實(shí)現(xiàn)日志記錄、安全控制、性能監(jiān)控等橫切關(guān)注點(diǎn)的分離,在傳統(tǒng)的 AOP 實(shí)現(xiàn)中,切面邏輯往往是固定的,難以動(dòng)態(tài)調(diào)整,本文將詳細(xì)探討如何利用 Spring Boot 實(shí)現(xiàn)動(dòng)態(tài)插拔的 AOP,需要的朋友可以參考下
    2025-01-01
  • 使用Java實(shí)現(xiàn)簡(jiǎn)單的區(qū)塊鏈程序的方法

    使用Java實(shí)現(xiàn)簡(jiǎn)單的區(qū)塊鏈程序的方法

    這篇文章主要介紹了使用Java實(shí)現(xiàn)簡(jiǎn)單的區(qū)塊鏈程序的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • spring boot 實(shí)現(xiàn)配置多個(gè)DispatcherServlet最簡(jiǎn)單方式

    spring boot 實(shí)現(xiàn)配置多個(gè)DispatcherServlet最簡(jiǎn)單方式

    這篇文章主要介紹了spring boot 實(shí)現(xiàn)配置多個(gè)DispatcherServlet最簡(jiǎn)單方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • SpringDataJpa的使用之一對(duì)一、一對(duì)多、多對(duì)多?關(guān)系映射問(wèn)題

    SpringDataJpa的使用之一對(duì)一、一對(duì)多、多對(duì)多?關(guān)系映射問(wèn)題

    這篇文章主要介紹了SpringDataJpa的使用?--?一對(duì)一、一對(duì)多、多對(duì)多關(guān)系映射,本文主要講述?@OneToOne、@OneToMany、@ManyToOne、@ManyToMany?這四個(gè)關(guān)系映射注解的使用,以及其對(duì)應(yīng)的級(jí)聯(lián)關(guān)系,需要的朋友可以參考下
    2022-07-07
  • Java多線程之同步工具類Exchanger

    Java多線程之同步工具類Exchanger

    這篇文章主要介紹了Java多線程之同步工具類Exchanger,Exchanger 是一個(gè)用于線程間協(xié)作的工具類,Exchanger用于進(jìn)行線程間的數(shù)據(jù)交換,它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn),兩個(gè)線程可以交換彼此的數(shù)據(jù),下面來(lái)看看具體內(nèi)容吧
    2021-10-10
  • springboot之Jpa通用接口及公共方法使用示例

    springboot之Jpa通用接口及公共方法使用示例

    這篇文章主要為大家介紹了springboot?之Jpa通用接口及公共方法使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Spring Boot配置特定屬性spring.profiles的方法

    Spring Boot配置特定屬性spring.profiles的方法

    這篇文章主要介紹了Spring Boot配置特定屬性spring.profiles的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • 使用Spring Boot Mybatis 搞反向工程的步驟

    使用Spring Boot Mybatis 搞反向工程的步驟

    這篇文章主要介紹了使用Spring Boot Mybatis 搞反向工程的步驟,幫助大家更好的理解和使用spring boot框架,感興趣的朋友可以了解下
    2021-01-01
  • Java中JVM的雙親委派、內(nèi)存溢出、垃圾回收和調(diào)優(yōu)詳解

    Java中JVM的雙親委派、內(nèi)存溢出、垃圾回收和調(diào)優(yōu)詳解

    這篇文章主要介紹了Java中JVM的雙親委派、內(nèi)存溢出、垃圾回收和調(diào)優(yōu)詳解,類加載器是Java虛擬機(jī)(JVM)的一個(gè)重要組成部分,它的主要作用是將類的字節(jié)碼加載到內(nèi)存中,并生成對(duì)應(yīng)的Class對(duì)象,需要的朋友可以參考下
    2023-07-07
  • java中如何截取字符串最后一位

    java中如何截取字符串最后一位

    這篇文章主要介紹了java中如何截取字符串最后一位的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評(píng)論