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

Java代理模式(Proxy)實(shí)現(xiàn)方法詳解

 更新時(shí)間:2025年04月21日 09:30:46   作者:冰糖心書房  
這篇文章主要介紹了Java代理模式(Proxy)實(shí)現(xiàn)的相關(guān)資料,代理模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,通過引入代理對象來控制對目標(biāo)對象的訪問,代理模式的優(yōu)點(diǎn)包括職責(zé)清晰、擴(kuò)展性好、保護(hù)目標(biāo)對象和增強(qiáng)功能,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、什么是代理模式?

  • 定義: 代理模式是一種結(jié)構(gòu)型設(shè)計(jì)模式。 它為另一個(gè)對象(目標(biāo)對象/被代理對象)提供一個(gè)代理(或占位符),以控制對這個(gè)對象的訪問。
  • 核心思想: 通過引入一個(gè)代理對象,客戶端不直接訪問目標(biāo)對象,而是通過代理對象來間接訪問目標(biāo)對象。 代理對象可以控制對目標(biāo)對象的訪問,并可以在訪問前后添加額外的操作。
  • 意圖: 控制對一個(gè)對象的訪問,可以延遲加載、訪問控制、增強(qiáng)功能等。

二、代理模式的結(jié)構(gòu)

代理模式通常包含以下幾個(gè)角色:

  • Subject (抽象主題):

    • 定義了 RealSubject 和 Proxy 的共同接口。 客戶端通過 Subject 接口訪問目標(biāo)對象。
    • 通常是一個(gè)接口或抽象類。
  • RealSubject (真實(shí)主題/目標(biāo)對象/被代理對象):

    • 定義了真正的業(yè)務(wù)邏輯。
    • 實(shí)現(xiàn)了 Subject 接口。
  • Proxy (代理):

    • 持有 RealSubject 對象的引用。
    • 實(shí)現(xiàn)了 Subject 接口,與 RealSubject 具有相同的方法。
    • 控制對 RealSubject 對象的訪問,并可以在訪問前后添加額外的操作。
    • 客戶端通過 Proxy 對象間接訪問 RealSubject 對象。

UML 類圖:

+----------------+       +----------------+       +----------------+
|   <<Subject>>   |       |     Proxy      |       |  RealSubject   |
+----------------+       +----------------+       +----------------+
| +request()     |------>| -realSubject   |------>| +request()     |
+----------------+       | +request()     |       +----------------+
                             +preRequest()
                             +postRequest()

三、代理模式的類型

根據(jù)代理的創(chuàng)建時(shí)間和功能,可以將代理模式分為以下幾種類型:

  • 靜態(tài)代理 (Static Proxy):

    • 特點(diǎn): 在編譯時(shí)就已經(jīng)確定了代理類和被代理類之間的關(guān)系。 代理類和被代理類都需要實(shí)現(xiàn)相同的接口。
    • 優(yōu)點(diǎn): 實(shí)現(xiàn)簡單,易于理解。
    • 缺點(diǎn):
      • 代碼冗余: 如果需要代理多個(gè)類,就需要?jiǎng)?chuàng)建多個(gè)代理類,導(dǎo)致代碼冗余。
      • 可維護(hù)性差: 如果接口發(fā)生變化,代理類和被代理類都需要進(jìn)行修改。
  • 動(dòng)態(tài)代理 (Dynamic Proxy):

    • 特點(diǎn): 在運(yùn)行時(shí)動(dòng)態(tài)地生成代理類,無需手動(dòng)創(chuàng)建代理類。
    • 優(yōu)點(diǎn):
      • 靈活性高: 可以代理任何實(shí)現(xiàn)了接口的類,無需修改原始代碼。
      • 代碼復(fù)用: 可以使用同一個(gè)代理類來代理多個(gè)不同的類。
      • 可維護(hù)性好: 如果接口發(fā)生變化,只需要修改代理邏輯,無需修改被代理類。
    • 缺點(diǎn):
      • 實(shí)現(xiàn)復(fù)雜: 動(dòng)態(tài)代理的實(shí)現(xiàn)比靜態(tài)代理復(fù)雜。
      • 性能開銷: 動(dòng)態(tài)代理需要使用反射機(jī)制,性能比靜態(tài)代理略低。
    • Java 中的動(dòng)態(tài)代理:
      • JDK 動(dòng)態(tài)代理: Java 提供的內(nèi)置動(dòng)態(tài)代理機(jī)制,只能代理實(shí)現(xiàn)了接口的類。
      • CGLIB 動(dòng)態(tài)代理: 第三方庫提供的動(dòng)態(tài)代理機(jī)制,可以代理沒有實(shí)現(xiàn)接口的類。
  • 其他代理

    • 保護(hù)代理 用于控制對敏感對象的訪問。
    • 遠(yuǎn)程代理 用于訪問遠(yuǎn)程對象。
    • 虛擬代理 通過代理延遲創(chuàng)建開銷大的對象

四、代理模式的實(shí)現(xiàn)方式 (Java)

  • 靜態(tài)代理:

    // 抽象主題
    interface Image {
        void display();
    }
    
    // 真實(shí)主題
    class RealImage implements Image {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        @Override
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 代理
    class ImageProxy implements Image {
        private RealImage realImage;
        private String filename;
    
        public ImageProxy(String filename) {
            this.filename = filename;
        }
    
        @Override
        public void display() {
            if (realImage == null) {
                realImage = new RealImage(filename);
            }
            realImage.display();
        }
    }
    
    // 客戶端代碼
    public class StaticProxyExample {
        public static void main(String[] args) {
            Image image = new ImageProxy("test_image.jpg");
    
            // 第一次調(diào)用 display() 方法,會(huì)加載圖片
            image.display();
    
            // 第二次調(diào)用 display() 方法,不會(huì)再次加載圖片
            image.display();
        }
    }
    
  • JDK 動(dòng)態(tài)代理:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // 抽象主題
    interface Image {
        void display();
    }
    
    // 真實(shí)主題
    class RealImage implements Image {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        @Override
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 調(diào)用處理器
    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 {
            // 在調(diào)用目標(biāo)方法之前執(zhí)行的操作
            System.out.println("Before invoking method: " + method.getName());
    
            // 調(diào)用目標(biāo)方法
            Object result = method.invoke(target, args);
    
            // 在調(diào)用目標(biāo)方法之后執(zhí)行的操作
            System.out.println("After invoking method: " + method.getName());
    
            return result;
        }
    }
    
    // 客戶端代碼
    public class JDKDynamicProxyExample {
        public static void main(String[] args) {
            // 創(chuàng)建被代理對象
            Image realImage = new RealImage("test_image.jpg");
    
            // 創(chuàng)建調(diào)用處理器
            ImageInvocationHandler handler = new ImageInvocationHandler(realImage);
    
            // 創(chuàng)建代理對象
            Image proxy = (Image) Proxy.newProxyInstance(
                    Image.class.getClassLoader(), // 類加載器
                    new Class[] {Image.class}, // 代理類實(shí)現(xiàn)的接口列表
                    handler // 調(diào)用處理器
            );
    
            // 通過代理對象調(diào)用方法
            proxy.display();
        }
    }
    
  • CGLIB 動(dòng)態(tài)代理:

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    // 真實(shí)主題 (不需要實(shí)現(xiàn)接口)
    class RealImage {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
        public RealImage(){} //需要一個(gè)無參構(gòu)造函數(shù)
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 方法攔截器
    class ImageMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 在調(diào)用目標(biāo)方法之前執(zhí)行的操作
            System.out.println("Before invoking method: " + method.getName());
    
            // 調(diào)用目標(biāo)方法
            Object result = proxy.invokeSuper(obj, args);
    
            // 在調(diào)用目標(biāo)方法之后執(zhí)行的操作
            System.out.println("After invoking method: " + method.getName());
    
            return result;
        }
    }
    
    // 客戶端代碼
    public class CGLIBDynamicProxyExample {
        public static void main(String[] args) {
            // 創(chuàng)建 Enhancer 對象
            Enhancer enhancer = new Enhancer();
    
            // 設(shè)置超類
            enhancer.setSuperclass(RealImage.class);
    
            // 設(shè)置回調(diào)
            enhancer.setCallback(new ImageMethodInterceptor());
    
            // 創(chuàng)建代理對象
            RealImage proxy = (RealImage) enhancer.create();
    
            // 通過代理對象調(diào)用方法
            proxy.display();
        }
    }
    

五、代理模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 職責(zé)清晰: 將客戶端與目標(biāo)對象分離,降低了耦合度。
  • 擴(kuò)展性好: 可以通過添加新的代理類來擴(kuò)展系統(tǒng)功能,而無需修改原始代碼。
  • 保護(hù)目標(biāo)對象: 代理對象可以控制對目標(biāo)對象的訪問,保護(hù)目標(biāo)對象免受惡意訪問。
  • 增強(qiáng)目標(biāo)對象的功能: 代理對象可以在訪問目標(biāo)對象前后添加額外的操作,例如日志記錄、安全檢查、延遲加載等。

缺點(diǎn):

  • 增加系統(tǒng)復(fù)雜性: 引入代理對象會(huì)增加系統(tǒng)的復(fù)雜性。
  • 可能降低性能: 代理對象需要進(jìn)行額外的處理,可能會(huì)降低程序的性能。

六、代理模式的應(yīng)用場景

  • 遠(yuǎn)程代理 (Remote Proxy): 為遠(yuǎn)程對象提供一個(gè)本地代理,隱藏遠(yuǎn)程對象的具體實(shí)現(xiàn)細(xì)節(jié)。
  • 虛擬代理 (Virtual Proxy): 為創(chuàng)建開銷大的對象提供一個(gè)代理,延遲對象的創(chuàng)建,直到真正需要使用時(shí)才創(chuàng)建。
  • 保護(hù)代理 (Protection Proxy): 控制對敏感對象的訪問,只允許具有特定權(quán)限的客戶端訪問。
  • 緩存代理 (Cache Proxy): 為訪問開銷大的對象提供一個(gè)緩存,提高訪問效率。
  • 智能引用代理 (Smart Reference Proxy): 在訪問對象時(shí)執(zhí)行額外的操作,例如引用計(jì)數(shù)、對象鎖定等。
  • AOP (面向切面編程): 使用動(dòng)態(tài)代理來實(shí)現(xiàn) AOP,例如 Spring AOP。
  • 延遲加載 (Lazy Loading): 例如,Hibernate 中的延遲加載機(jī)制。
  • 防火墻代理: 控制網(wǎng)絡(luò)訪問,保護(hù)內(nèi)部網(wǎng)絡(luò)。

七、總結(jié)

代理模式是一種非常有用的設(shè)計(jì)模式,它可以控制對對象的訪問,并可以在訪問前后添加額外的操作。 在 Java 中,可以使用靜態(tài)代理、JDK 動(dòng)態(tài)代理和 CGLIB 動(dòng)態(tài)代理來實(shí)現(xiàn)代理模式。 選擇哪種實(shí)現(xiàn)方式取決于具體的應(yīng)用場景和需求。

到此這篇關(guān)于Java代理模式(Proxy)實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Java代理模式Proxy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud feign服務(wù)熔斷下的異常處理操作

    SpringCloud feign服務(wù)熔斷下的異常處理操作

    這篇文章主要介紹了SpringCloud feign服務(wù)熔斷下的異常處理操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringAOP 如何通過JoinPoint獲取參數(shù)名和值

    SpringAOP 如何通過JoinPoint獲取參數(shù)名和值

    這篇文章主要介紹了SpringAOP 通過JoinPoint獲取參數(shù)名和值的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java中內(nèi)核線程理論及實(shí)例詳解

    Java中內(nèi)核線程理論及實(shí)例詳解

    在本篇文章里小編給大家整理了一篇關(guān)于Java中內(nèi)核線程理論及實(shí)例詳解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-03-03
  • 解析Java的Spring框架的BeanPostProcessor發(fā)布處理器

    解析Java的Spring框架的BeanPostProcessor發(fā)布處理器

    這篇文章主要介紹了Java的Spring框架的BeanPostProcessor發(fā)布處理器,Spring是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • Java調(diào)用用戶芝麻信用分

    Java調(diào)用用戶芝麻信用分

    這篇文章主要為大家詳細(xì)介紹了Java調(diào)用用戶芝麻信用分,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Java Servlet請求重定向的方法

    Java Servlet請求重定向的方法

    這篇文章主要介紹了使用Java Servlet請求重定向的方法,幫助大家更好的理解和學(xué)習(xí)Java Servlet的相關(guān)知識(shí),感興趣的朋友可以了解下
    2020-11-11
  • Java實(shí)現(xiàn)Word/Excel/TXT轉(zhuǎn)PDF的方法

    Java實(shí)現(xiàn)Word/Excel/TXT轉(zhuǎn)PDF的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)Word/Excel/TXT轉(zhuǎn)PDF的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-01-01
  • java多線程編程之java線程簡介

    java多線程編程之java線程簡介

    線程是程序運(yùn)行的基本執(zhí)行單元,線程不僅可以共享進(jìn)程的內(nèi)存,而且還擁有一個(gè)屬于自己的內(nèi)存空間,這段內(nèi)存空間也叫做線程棧
    2014-01-01
  • 解決Maven靜態(tài)資源過濾問題

    解決Maven靜態(tài)資源過濾問題

    在我們使用Maven構(gòu)建項(xiàng)目的時(shí)候,會(huì)默認(rèn)過濾掉靜態(tài)資源,所以,需要手動(dòng)來配置,本文就介紹一下Maven靜態(tài)資源過濾的問題解決,感興趣的可以了解一下
    2021-06-06
  • Spring Security OAuth2 token權(quán)限隔離實(shí)例解析

    Spring Security OAuth2 token權(quán)限隔離實(shí)例解析

    這篇文章主要介紹了Spring Security OAuth2 token權(quán)限隔離實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11

最新評(píng)論