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

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

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

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

代理模式

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

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

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

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

靜態(tài)代理

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

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

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

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

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

那我們只需寫兩個代理類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("售后服務");
    }
}
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("售后服務");
    }
}

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

輸出:
售前了解
出售羅技鼠標
售后服務
售前了解
出售HHKB鍵盤
售后服務

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

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

那么這個時候就可以使用動態(tài)代理來解決了

動態(tài)代理

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

JDK動態(tài)代理

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

還是上面的例子,用JDK動態(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("售后服務");
        return invoke;
    }
}

當我們調(diào)用代理類對象的方法時,這個“調(diào)用”會轉(zhuǎn)送到invoke方法中,

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

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

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

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

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

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

CGLIB動態(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(){
        //設置需要創(chuàng)建子類的類
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        //創(chuàng)建代理對象
        return enhancer.create();
    }
    // o: cglib 動態(tài)生成的代理類的實例
    // method:實體類所調(diào)用的都被代理的方法的引用
    // objects 參數(shù)列表
    // methodProxy:生成的代理類對方法的代理引用
    @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動態(tài)代理實現(xiàn)接口,CGLIB動態(tài)繼承思想
  • JDK動態(tài)代理(目標對象存在接口時)執(zhí)行效率高于CIGLIB
  • 如果對象有接口實現(xiàn),選擇JDK代理,如果沒有接口實現(xiàn)選擇CGILB代理

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

相關文章

  • java 中使用匿名類直接new接口詳解及實例代碼

    java 中使用匿名類直接new接口詳解及實例代碼

    這篇文章主要介紹了java 中使用匿名類直接new接口詳解及實例代碼的相關資料,需要的朋友可以參考下
    2017-03-03
  • Java實現(xiàn)數(shù)據(jù)庫連接池的方法

    Java實現(xiàn)數(shù)據(jù)庫連接池的方法

    這篇文章主要介紹了Java實現(xiàn)數(shù)據(jù)庫連接池的方法,涉及java數(shù)據(jù)庫連接池的創(chuàng)建、連接、刷新、關閉及狀態(tài)獲取的常用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • Java集合ConcurrentHashMap詳解

    Java集合ConcurrentHashMap詳解

    ConcurrentHashMap?是?J.U.C?包里面提供的一個線程安全并且高效的?HashMap,所以ConcurrentHashMap?在并發(fā)編程的場景中使用的頻率比較高
    2023-01-01
  • 詳談jvm線程??臻g內(nèi)存分配位置

    詳談jvm線程??臻g內(nèi)存分配位置

    這篇文章主要介紹了jvm線程棧空間內(nèi)存分配位置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java微信公眾號開發(fā)案例

    java微信公眾號開發(fā)案例

    這篇文章主要為大家詳細介紹了java微信公眾號開發(fā)案例,如何接入公眾號,訂閱號怎么樣接收消息,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Java解析http協(xié)議字符串的方法實現(xiàn)

    Java解析http協(xié)議字符串的方法實現(xiàn)

    本文主要介紹了Java解析http協(xié)議字符串的方法實現(xiàn),我們探討了如何使用Java解析HTTP協(xié)議字符串,并將其封裝成了一個HttpRequest類,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • Mybatis Plus 實現(xiàn)批量插入的示例代碼

    Mybatis Plus 實現(xiàn)批量插入的示例代碼

    本文主要介紹了Mybatis Plus 實現(xiàn)批量插入的示例代碼,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例

    JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例

    本篇文章主要介紹了JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Spring?AOP對嵌套方法不起作用的解決

    Spring?AOP對嵌套方法不起作用的解決

    這篇文章主要介紹了Spring?AOP對嵌套方法不起作用的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 詳解Spring AOP 攔截器的基本實現(xiàn)

    詳解Spring AOP 攔截器的基本實現(xiàn)

    本篇文章主要介紹了詳解Spring AOP 攔截器的基本實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03

最新評論