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

Java深入分析動(dòng)態(tài)代理

 更新時(shí)間:2022年07月13日 08:47:59   作者:少年.  
動(dòng)態(tài)代理指的是,代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時(shí)候確定的,客戶通過代理類來調(diào)用目標(biāo)對(duì)象的方法,是在程序運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)的創(chuàng)建目標(biāo)類的代理對(duì)象。本文將通過案例詳細(xì)講解一下Java動(dòng)態(tài)代理的原理及實(shí)現(xiàn),需要的可以參考一下

"代理"這個(gè)詞相信大家并不陌生,簡單來說就是代替廠家來售賣商品,代理替代廠家售賣商品,顧客找代理購買商品。也就是說:1)顧客和廠家之間是不可見的,顧客不知道背后的廠家是誰。2)代理可以對(duì)顧客進(jìn)行“定位”,更精確的售賣給需要的客戶群體。

代理模式

代理模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問,也就是創(chuàng)建一個(gè)代理對(duì)象作為客戶端和目標(biāo)對(duì)象之間的中介,主要目的就是保護(hù)目標(biāo)對(duì)象或增強(qiáng)目標(biāo)對(duì)象

通過使用代理模式,通常有以下兩個(gè)優(yōu)點(diǎn):

\1) 可以隱藏被代理類的實(shí)現(xiàn)

\2) 可以實(shí)現(xiàn)客戶與被代理類間的解耦,在不修改被代理類代碼的情況下能夠做一些額外的處理

靜態(tài)代理

所謂的動(dòng)態(tài)代理,就是通過聲明一個(gè)明確的代理類來訪問源對(duì)象,一個(gè)代理只能服務(wù)于一種產(chǎn)品,當(dāng)有n種產(chǎn)品時(shí),就需要n個(gè)代理,這樣就不利于業(yè)務(wù)的發(fā)展。

舉例:我們有兩個(gè)接口,Mouse和Keyboard,每個(gè)接口都有一個(gè)實(shí)現(xiàn)類

實(shí)現(xiàn)類中的代碼如下:

public class LogitechMouse implements Mouse{
    @Override
    public void sell() {
        System.out.println("出售羅技鼠標(biāo)");
    }
}
public class HHKBKeyboard implements Keyboard{
    @Override
    public void sell() {
        System.out.println("出售HHKB鍵盤");
    }
}

現(xiàn)在我們要做的就是讓代理在調(diào)用sell()前輸出一句售前了解,調(diào)用后輸出一句售后服務(wù)

那我們只需寫兩個(gè)代理類MouseProxyKeyboardProxy

public class MouseProxy implements Mouse {
    private Mouse mouse;

    public MouseProxy(Mouse mouse) {
        this.mouse = mouse;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        mouse.sell();
        System.out.println("售后服務(wù)");
    }
}
public class KeyboardProxy implements Keyboard{
    private Keyboard keyboard;
    public KeyboardProxy(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        keyboard.sell();
        System.out.println("售后服務(wù)");
    }
}

最終執(zhí)行為:

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        MouseProxy mouseProxy = new MouseProxy(logitechMouse);
        mouseProxy.sell();
        Keyboard hhkbKeyboard = new HHKBKeyboard();
        KeyboardProxy keyboardProxy = new KeyboardProxy(hhkbKeyboard);
        keyboardProxy.sell();
    }
}

輸出:
售前了解
出售羅技鼠標(biāo)
售后服務(wù)
售前了解
出售HHKB鍵盤
售后服務(wù)

靜態(tài)代理的代碼非常簡單易懂,這種模式雖好,但是也有明顯的缺點(diǎn):

  • 會(huì)存在大量冗余的代理類,這里只有兩個(gè)接口,如果有n個(gè)接口,那么就要定義n個(gè)代理類。
  • 不易維護(hù),一旦接口更改,代理類和被代理類都要更改。

那么這個(gè)時(shí)候就可以使用動(dòng)態(tài)代理來解決了

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

代理類在程序運(yùn)行時(shí)創(chuàng)建代理的方式叫動(dòng)態(tài)代理,也就是說代理類并不是在java代碼中定義的,而是在運(yùn)行的時(shí)候動(dòng)態(tài)生成的

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

JDK從1.3版本就開始支持動(dòng)態(tài)代理類的創(chuàng)建。主要核心類只有2個(gè):java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler

還是上面的例子,用JDK動(dòng)態(tài)代理如下:

public class JDKProxy implements InvocationHandler {
    private Object object;
    public JDKProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, args);
        System.out.println("售后服務(wù)");
        return invoke;
    }
}

當(dāng)我們調(diào)用代理類對(duì)象的方法時(shí),這個(gè)“調(diào)用”會(huì)轉(zhuǎn)送到invoke方法中,

代理類對(duì)象作為proxy參數(shù)傳入,

參數(shù)method標(biāo)識(shí)了我們具體調(diào)用的是代理類的哪個(gè)方法,

args為這個(gè)方法的參數(shù)。

這樣一來,我們對(duì)代理類中的所有方法的調(diào)用都會(huì)變?yōu)閷?duì)invoke的調(diào)用,這樣我們可以在invoke方法中添加統(tǒng)一的處理邏輯(也可以根據(jù)method參數(shù)對(duì)不同的代理類方法做不同的處理)。因此我們可以在中介類的invoke方法中實(shí)現(xiàn)輸出售前了解,再調(diào)用被代理類的方法,再輸出售后服務(wù)。

執(zhí)行代碼

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        JDKProxy jdkProxy = new JDKProxy(logitechMouse);
        Mouse mouse= (Mouse)Proxy.newProxyInstance(jdkProxy.getClass().getClassLoader(), new Class[]{Mouse.class}, jdkProxy);
        mouse.sell();
        HHKBKeyboard hhkbKeyboard = new HHKBKeyboard();
        JDKProxy jdkProxy1 = new JDKProxy(hhkbKeyboard);
        Keyboard keyboard = (Keyboard)Proxy.newProxyInstance(jdkProxy1.getClass().getClassLoader(), new Class[]{Keyboard.class}, jdkProxy1);
        keyboard.sell();
    }
}

可以看到無論多少個(gè)接口,只需要一個(gè)代理類就可以了。

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

代理類:

public class CGLIBProcy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    private Object object;
    public CGLIBProcy(Object object) {
        this.object = object;
    }
    public Object getProxy(){
        //設(shè)置需要?jiǎng)?chuàng)建子類的類
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        //創(chuàng)建代理對(duì)象
        return enhancer.create();
    }
    // o: cglib 動(dòng)態(tài)生成的代理類的實(shí)例
    // method:實(shí)體類所調(diào)用的都被代理的方法的引用
    // objects 參數(shù)列表
    // methodProxy:生成的代理類對(duì)方法的代理引用
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, objects);
        System.out.println("售后處理");
        return invoke;
    }
}

執(zhí)行代碼:

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        CGLIBProcy cglibProcy = new CGLIBProcy(logitechMouse);
        Mouse proxy = (Mouse)cglibProcy.getProxy();
        proxy.sell();
        cglibProcy = new CGLIBProcy(new HHKBKeyboard());
        Keyboard keyboard = (Keyboard)cglibProcy.getProxy();
        keyboard.sell();
    }
}

JDK代理與CGLIB代理的區(qū)別

  • JDK動(dòng)態(tài)代理實(shí)現(xiàn)接口,CGLIB動(dòng)態(tài)繼承思想
  • JDK動(dòng)態(tài)代理(目標(biāo)對(duì)象存在接口時(shí))執(zhí)行效率高于CIGLIB
  • 如果對(duì)象有接口實(shí)現(xiàn),選擇JDK代理,如果沒有接口實(shí)現(xiàn)選擇CGILB代理

到此這篇關(guān)于Java深入分析動(dòng)態(tài)代理的文章就介紹到這了,更多相關(guān)Java動(dòng)態(tài)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java byte數(shù)組與16進(jìn)制間相互轉(zhuǎn)換的示例

    java byte數(shù)組與16進(jìn)制間相互轉(zhuǎn)換的示例

    這篇文章主要介紹了java byte數(shù)組與16進(jìn)制間相互轉(zhuǎn)換的示例,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-10-10
  • Spring項(xiàng)目中如何自定義序列化工具

    Spring項(xiàng)目中如何自定義序列化工具

    這篇文章主要為大家詳細(xì)介紹了Spring項(xiàng)目中自定義序列化工具的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • Spring純注解開發(fā)模式讓開發(fā)簡化更簡化

    Spring純注解開發(fā)模式讓開發(fā)簡化更簡化

    Spring3.0引入了純注解開發(fā)的模式,框架的誕生是為了簡化開發(fā),那注解開發(fā)就是簡化再簡化。Spring的特性在整合MyBatis方面體現(xiàn)的淋漓盡致哦
    2022-08-08
  • Spring Boot實(shí)戰(zhàn)之模板引擎

    Spring Boot實(shí)戰(zhàn)之模板引擎

    這篇文章主要介紹了Spring Boot實(shí)戰(zhàn)之模板引擎,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • JAVA 文件監(jiān)控 WatchService的示例方法

    JAVA 文件監(jiān)控 WatchService的示例方法

    本篇文章主要介紹了JAVA 文件監(jiān)控 WatchService的示例方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運(yùn)行 java 代碼

    MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運(yùn)行 java 代碼

    這篇文章主要介紹了MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運(yùn)行 java 代碼,需要的朋友可以參考下
    2014-10-10
  • spring cloud實(shí)現(xiàn)Eureka注冊(cè)中心的HA的方法

    spring cloud實(shí)現(xiàn)Eureka注冊(cè)中心的HA的方法

    本篇文章主要介紹了spring cloud實(shí)現(xiàn)Eureka注冊(cè)中心的HA的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • SpringBoot工程下使用OpenFeign的坑及解決

    SpringBoot工程下使用OpenFeign的坑及解決

    這篇文章主要介紹了SpringBoot工程下使用OpenFeign的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring Boot整合Swagger2的完整步驟詳解

    Spring Boot整合Swagger2的完整步驟詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot整合Swagger2的完整步驟,文中通過示例代碼將整合的步驟一步步介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • SpringBoot獲取Request對(duì)象的常見方法

    SpringBoot獲取Request對(duì)象的常見方法

    HttpServletRequest 簡稱 Request,它是一個(gè) Servlet API 提供的對(duì)象,用于獲取客戶端發(fā)起的 HTTP 請(qǐng)求信息,那么在SpringBoot中,獲取 Request對(duì)象的方法有哪些呢,本文小編將給大家講講SpringBoot獲取Request對(duì)象的常見方法
    2023-08-08

最新評(píng)論

开平市| 盐津县| 观塘区| 建宁县| 乐至县| 柳林县| 光山县| 曲周县| 高邑县| 怀柔区| 永吉县| 宁夏| 柳江县| 南郑县| 沧源| 望都县| 尚义县| 岳阳市| 永安市| 周至县| 潞西市| 驻马店市| 恩平市| 古交市| 潞城市| 嘉禾县| 鞍山市| 隆安县| 文水县| 浦江县| 石门县| 贵州省| 巴林右旗| 乐至县| 郎溪县| 屯昌县| 张家川| 辛集市| 新营市| 稷山县| 五河县|