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

Java代理模式之靜態(tài)代理與動態(tài)代理的區(qū)別及優(yōu)缺點

 更新時間:2023年06月27日 09:16:31   作者:蜀山劍客李沐白  
代理模式是一種常用的設(shè)計模式,它允許通過引入一個代理對象來控制對目標(biāo)對象的訪問,在Java中,代理模式被廣泛應(yīng)用,它可以提供額外的功能,如權(quán)限檢查、緩存、日志記錄等,本文將介紹靜態(tài)代理與動態(tài)代理的區(qū)別及優(yōu)缺點,需要的朋友可以參考下

1. 代理模式的定義

代理模式(Proxy Pattern)是指通過代理對象控制對目標(biāo)對象的訪問,并在不改變目標(biāo)對象的情況下添加額外的功能或控制訪問。代理對象和目標(biāo)對象實現(xiàn)相同的接口,使得客戶端可以通過代理對象間接地訪問目標(biāo)對象。

代理模式屬于結(jié)構(gòu)型設(shè)計模式,它在系統(tǒng)中引入了一個代理對象,該對象代替了客戶端直接訪問目標(biāo)對象,從而可以在目標(biāo)對象的基礎(chǔ)上增加一些額外的功能或控制訪問。

2. 代理模式的原理

代理模式的核心思想是引入一個代理對象來控制對目標(biāo)對象的訪問。代理對象和目標(biāo)對象實現(xiàn)相同的接口,使得客戶端可以通過代理對象間接地訪問目標(biāo)對象。代理對象負(fù)責(zé)處理客戶端的請求,并在必要時將請求轉(zhuǎn)發(fā)給目標(biāo)對象。在這個過程中,代理對象可以添加額外的邏輯,如權(quán)限檢查、緩存、日志記錄等。

代理模式的主要角色有:

  • 抽象主題(Subject):定義了代理對象和目標(biāo)對象的共同接口,在Java中通常是一個接口或抽象類。
  • 目標(biāo)對象(RealSubject):定義了代理對象所代表的真實對象,是業(yè)務(wù)邏輯的具體執(zhí)行者。
  • 代理對象(Proxy):持有對目標(biāo)對象的引用,并實現(xiàn)了與目標(biāo)對象相同的接口,在方法調(diào)用前后進(jìn)行額外操作。

代理模式的工作流程如下:

  • 客戶端向代理對象發(fā)送請求。
  • 代理對象收到請求后,可以在請求被轉(zhuǎn)發(fā)給目標(biāo)對象之前或之后執(zhí)行一些額外的邏輯。
  • 代理對象將請求轉(zhuǎn)發(fā)給目標(biāo)對象。
  • 目標(biāo)對象執(zhí)行具體的業(yè)務(wù)邏輯并返回結(jié)果。
  • 代理對象可以在目標(biāo)對象返回結(jié)果之前或之后執(zhí)行一些額外的操作。
  • 代理對象將結(jié)果返回給客戶端。

通過引入代理對象,代理模式可以控制對目標(biāo)對象的訪問,并在不改變目標(biāo)對象的情況下添加額外的功能或控制訪問。

3. 代理模式的實現(xiàn)方式

在Java中,代理模式主要有兩種實現(xiàn)方式:靜態(tài)代理和動態(tài)代理。

3.1 靜態(tài)代理

靜態(tài)代理是指在編譯時就已經(jīng)確定了代理對象和目標(biāo)對象的關(guān)系,代理類是通過手動編寫代碼來實現(xiàn)的。在靜態(tài)代理中,代理類和目標(biāo)類都實現(xiàn)相同的接口,代理類持有目標(biāo)對象,并在方法調(diào)用前后進(jìn)行額外的操作。

靜態(tài)代理的工作原理如下:

  • 定義一個接口(或抽象類)作為目標(biāo)接口,目標(biāo)對象實現(xiàn)這個接口。
  • 創(chuàng)建一個代理類,實現(xiàn)目標(biāo)接口,并持有目標(biāo)對象的引用。
  • 在代理類中重寫目標(biāo)接口的方法,在方法調(diào)用前后執(zhí)行需要的額外操作。
  • 客戶端使用代理對象來訪問目標(biāo)對象。

靜態(tài)代理的特點:

  • 需要手動編寫代理類,工作量較大。
  • 目標(biāo)對象必須實現(xiàn)接口。
  • 代理類和目標(biāo)類的關(guān)系在編譯時就確定了,無法動態(tài)改變。

靜態(tài)代理的應(yīng)用場景:

  • 安全控制:代理類可以在調(diào)用目標(biāo)方法前進(jìn)行權(quán)限檢查等安全控制。
  • 遠(yuǎn)程調(diào)用:代理類可以封裝網(wǎng)絡(luò)通信相關(guān)的細(xì)節(jié),使得調(diào)用遠(yuǎn)程方法就像調(diào)用本地方法一樣簡單。
  • 性能監(jiān)控:代理類可以收集方法的執(zhí)行時間、調(diào)用次數(shù)等信息,用于性能監(jiān)控和統(tǒng)計分析。

下面是一個簡單的靜態(tài)代理的示例代碼:

// 定義接口
public interface Image {
    void display();
}
// 目標(biāo)類
public class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }
    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }
    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}
// 代理類
public class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;
    public ImageProxy(String filename) {
        this.filename = filename;
    }
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}
// 測試類
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 使用代理對象顯示圖片
        Image image = new ImageProxy("test.jpg");
        image.display();
        // 圖片已加載,直接顯示,無需重新加載
        image.display();
    }
}

在上面的示例中,Image 是一個接口,RealImage 是目標(biāo)類,負(fù)責(zé)加載和顯示圖片。ImageProxy 是代理類,通過持有目標(biāo)類的引用,在需要時創(chuàng)建并使用目標(biāo)類。ProxyPatternDemo 是一個測試類,用于演示靜態(tài)代理的使用。

在測試類中,首先創(chuàng)建一個代理對象 ImageProxy,并調(diào)用 display() 方法顯示圖片。代理對象會在第一次調(diào)用 display() 方法時,創(chuàng)建真實對象 RealImage 并調(diào)用其 display() 方法加載和顯示圖片。在后續(xù)調(diào)用 display() 方法時,代理對象直接調(diào)用真實對象的 display() 方法,無需重新加載圖片。

靜態(tài)代理的缺點是需要手動編寫代理類,工作量較大。如果接口中的方法較多或頻繁變動,就需要頻繁修改代理類的代碼,增加了維護(hù)的難度。此外,靜態(tài)代理的代理類和目標(biāo)類之間存在緊耦合關(guān)系,一旦目標(biāo)類發(fā)生變化,代理類也需要相應(yīng)修改。

為了解決靜態(tài)代理的缺點,Java還提供了動態(tài)代理機(jī)制。

3.2 動態(tài)代理

動態(tài)代理是指在運行時生成代理對象,而無需手動編寫代理類。Java的動態(tài)代理機(jī)制是基于反射實現(xiàn)的,通過使用java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口來實現(xiàn)動態(tài)代理。

在動態(tài)代理中,代理類的創(chuàng)建和方法調(diào)用都是在運行時完成的。代理對象是在內(nèi)存中動態(tài)創(chuàng)建的,并實現(xiàn)了目標(biāo)對象的接口,同時持有目標(biāo)對象的引用。在方法調(diào)用時,代理對象通過調(diào)用InvocationHandler接口中的方法來處理請求,可以在方法調(diào)用前后執(zhí)行額外的操作。

動態(tài)代理的工作原理如下:

  • 定義一個接口,作為目標(biāo)接口。
  • 創(chuàng)建一個InvocationHandler接口的實現(xiàn)類,該類負(fù)責(zé)處理方法調(diào)用并執(zhí)行額外的操作。
  • 使用Proxy類的靜態(tài)方法newProxyInstance()生成代理對象,同時指定目標(biāo)對象和InvocationHandler。
  • 客戶端使用代理對象來訪問目標(biāo)對象的方法。

動態(tài)代理的特點:

  • 不需要手動編寫代理類,代理對象在運行時動態(tài)生成。
  • 目標(biāo)對象可以不實現(xiàn)接口,只需定義目標(biāo)對象的共同接口。
  • 代理對象和目標(biāo)對象的關(guān)系在運行時確定,可以動態(tài)改變。

動態(tài)代理的應(yīng)用場景:

  • AOP(面向切面編程):動態(tài)代理可以在目標(biāo)方法執(zhí)行前后執(zhí)行額外的操作,如權(quán)限檢查、事務(wù)管理等。它是實現(xiàn)AOP的一種常見方式。
  • 延遲加載:動態(tài)代理可以在目標(biāo)方法被調(diào)用時才進(jìn)行加載和初始化,實現(xiàn)延遲加載的效果。
  • 日志記錄:動態(tài)代理可以在目標(biāo)方法執(zhí)行前后記錄日志信息。

下面是一個簡單的動態(tài)代理的示例代碼:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定義接口
interface Image {
    void display();
}
// 目標(biāo)類
class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }
    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }
    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}
// InvocationHandler 實現(xiàn)類
class ImageInvocationHandler implements InvocationHandler {
    private Object target;
    public ImageInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After method: " + method.getName());
        return result;
    }
}
// 測試類
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 創(chuàng)建目標(biāo)對象
        Image realImage = new RealImage("test.jpg");
        // 創(chuàng)建 InvocationHandler 實例
        ImageInvocationHandler handler = new ImageInvocationHandler(realImage);
        // 創(chuàng)建代理對象
        Image imageProxy = (Image) Proxy.newProxyInstance(Image.class.getClassLoader(),
                new Class[]{Image.class}, handler);
        // 使用代理對象顯示圖片
        imageProxy.display();
    }
}

在上面的示例中,Image 是一個接口,RealImage 是目標(biāo)類,負(fù)責(zé)加載和顯示圖片。ImageInvocationHandlerInvocationHandler接口的實現(xiàn)類,用于處理方法調(diào)用并執(zhí)行額外的操作。ProxyPatternDemo 是一個測試類,用于演示動態(tài)代理的使用。

在測試類中,首先創(chuàng)建一個目標(biāo)對象 RealImage,然后創(chuàng)建一個 ImageInvocationHandler 實例,并將目標(biāo)對象傳入構(gòu)造函數(shù)。接下來,通過調(diào)用 Proxy 類的 newProxyInstance() 方法來生成代理對象。最后,使用代理對象調(diào)用 display() 方法顯示圖片。

在方法調(diào)用時,代理對象會調(diào)用 InvocationHandler 接口中的 invoke() 方法處理方法調(diào)用。在示例中,我們在 invoke() 方法中實現(xiàn)了打印方法名的額外操作,并通過反射調(diào)用目標(biāo)對象的方法。

以上就是Java代理模式之靜態(tài)代理與動態(tài)代理的區(qū)別及優(yōu)缺點的詳細(xì)內(nèi)容,更多關(guān)于Java 靜態(tài)與動態(tài)代理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAXB簡介_動力節(jié)點Java學(xué)院整理

    JAXB簡介_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了JAXB簡介的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Java異常處理之java.lang.ClassCastException問題

    Java異常處理之java.lang.ClassCastException問題

    這篇文章主要介紹了Java異常處理之java.lang.ClassCastException問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java業(yè)務(wù)校驗工具實現(xiàn)方法

    Java業(yè)務(wù)校驗工具實現(xiàn)方法

    這篇文章主要介紹了Java業(yè)務(wù)校驗工具實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java中的魔法類:sun.misc.Unsafe示例詳解

    Java中的魔法類:sun.misc.Unsafe示例詳解

    Java是一個安全的開發(fā)工具,它阻止開發(fā)人員犯很多低級的錯誤,而大部份的錯誤都是基于內(nèi)存管理方面的。如果你想搞破壞,可以使用Unsafe這個類。下面這篇文章主要給大家介紹了關(guān)于Java中魔法類:sun.misc.Unsafe的相關(guān)資料,需要的朋友可以參考下
    2018-05-05
  • 利用寶塔配置jdk環(huán)境的詳細(xì)圖文教程

    利用寶塔配置jdk環(huán)境的詳細(xì)圖文教程

    最近在寶塔面板上創(chuàng)建一個網(wǎng)站,為Java應(yīng)用程序提供運行環(huán)境,所以下面這篇文章主要給大家介紹了關(guān)于利用寶塔配置jdk環(huán)境的詳細(xì)圖文教程,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • SpringBoot HttpMessageConverter消息轉(zhuǎn)換器的使用詳解

    SpringBoot HttpMessageConverter消息轉(zhuǎn)換器的使用詳解

    在整個數(shù)據(jù)流轉(zhuǎn)過程中,前端的請求報文轉(zhuǎn)化為Java對象,Java對象轉(zhuǎn)化為響應(yīng)報文,這里就用到了消息轉(zhuǎn)換器HttpMessageConverter
    2022-06-06
  • Java生成指定范圍內(nèi)的一個隨機(jī)整數(shù)2種方式

    Java生成指定范圍內(nèi)的一個隨機(jī)整數(shù)2種方式

    本文主要介紹了Java生成指定范圍內(nèi)的一個隨機(jī)整數(shù)2種方式,主要使用Math.random()和Random.nextInt()這兩種,具有一定的參考價值,感興趣的可以了解一下
    2023-04-04
  • Java解決Collectors.toMap()空指針報錯問題的方法詳解

    Java解決Collectors.toMap()空指針報錯問題的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Java解決Collectors.toMap()空指針報錯問題的相關(guān)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-03-03
  • 解決Spring/SpringBoot @RequestParam注解無法讀取application/json格式數(shù)據(jù)問題

    解決Spring/SpringBoot @RequestParam注解無法讀取application/json

    本文介紹了如何通過自定義HandlerMethodArgumentResolver,使Spring的@RequestParam注解支持接收J(rèn)SON格式參數(shù),從而避免為少量參數(shù)單獨創(chuàng)建實體類,作者詳細(xì)分析了Spring源碼并給出了解決方案和相關(guān)配置步驟
    2025-10-10
  • springsecurity記住我登錄時訪問無權(quán)限接口跳轉(zhuǎn)登錄界面的處理方案

    springsecurity記住我登錄時訪問無權(quán)限接口跳轉(zhuǎn)登錄界面的處理方案

    這篇文章主要介紹了springsecurity記住我登錄時訪問無權(quán)限接口跳轉(zhuǎn)登錄界面的處理方案,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-02-02

最新評論

旌德县| 迭部县| 宝清县| 宁陕县| 南皮县| 响水县| 裕民县| 吴桥县| 连江县| 资溪县| 渝中区| 稷山县| 蛟河市| 本溪| 翁牛特旗| 大田县| 乐安县| 台州市| 平山县| 循化| 汾西县| 西城区| 尚志市| 金乡县| 永顺县| 柏乡县| 盐边县| 淅川县| 漳浦县| 博客| 自贡市| 涿州市| 天全县| 柏乡县| 辉县市| 芷江| 界首市| 砚山县| 高雄县| 建宁县| 聊城市|