国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

一文搞懂設計模式—代理模式

開發 前端
總的來說,代理模式通過引入代理對象,實現了對真實對象的間接訪問和控制,為系統的設計提供了一種簡潔而有效的解決方案。在日常的軟件開發中,合理地運用代理模式可以為系統帶來更好的結構和性能表現。

代理模式(Proxy Pattern)是一種結構型設計模式,也叫做委托模式,它允許你提供一個間接訪問對象的方式。

用一句話描述代理模式就是:為其他對象提供一種代理以控制對這個對象的訪問

使用場景

  • 遠程代理(Remote Proxy):用于在不同地址空間中代表對象,使得客戶端可以訪問遠程的對象。
  • 虛擬代理(Virtual Proxy):用于按需創建昂貴對象的代表,延遲對象的實例化,提高系統性能。
  • 保護代理(Protection Proxy):用于控制對真實對象的訪問權限,在訪問真實對象之前進行安全檢查。
  • 智能引用(Smart Reference):用于在訪問對象時執行額外的操作,如引用計數、懶加載等。
  • 日志記錄(Logging Proxy):用于記錄方法調用的日志信息,方便調試和監控系統運行狀態。
  • 權限控制(Access Control Proxy):用于控制用戶對對象的訪問權限,限制某些用戶的操作。
  • 延遲加載(Lazy Loading Proxy):用于延遲加載對象的數據,直到真正需要使用時才進行加載。

代理模式在Java中的Spring框架和Dubbo框架中都有廣泛的應用:

  • Spring框架中的AOP(面向切面編程):Spring使用代理模式實現AOP功能,允許開發者定義切面(Aspect),并通過代理機制將切面織入到目標對象的方法調用中,實現橫切關注點的管理,如日志記錄、事務管理等。
  • Dubbo框架中的遠程服務代理:Dubbo是一種高性能的分布式服務框架,其中的服務消費者與服務提供者之間的通信通過代理模式來實現。Dubbo會根據配置信息動態生成接口的代理實現類,在遠程調用時通過代理對象進行通信,隱藏了遠程調用的復雜性,使得調用方可以像調用本地方法一樣調用遠程服務。

通過代理模式,可以實現對對象的訪問控制、附加功能增強、性能優化等目的,提高系統的靈活性、可維護性和可擴展性。

具體實現

代理模式涉及以下幾個角色:

  • 抽象主題(Subject):是一個接口或抽象類,定義了真實主題和代理對象共同實現的方法,客戶端通過抽象主題訪問真實主題。
  • 真實主題(Real Subject):是真正執行業務邏輯的對象,實現了抽象主題定義的方法,是代理模式中被代理的對象。
  • 代理(Proxy):持有對真實主題的引用,可以控制對真實主題的訪問,在其自身的方法中可以調用真實主題的方法,同時也可以在調用前后執行一些附加操作。

實現代理模式步驟如下:

首先定義一個接口:

public interface Subject {
    void request();
}

然后實現真實主題類:

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Real Subject handles the request.");
    }
}

接著創建代理類:

public class Proxy implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }
    //前置處理
    private void preRequest() {
        System.out.println("Proxy performs pre-request actions.");
    }
    //后置處理
    private void postRequest() {
        System.out.println("Proxy performs post-request actions.");
    }
}

客戶端調用:

public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }

輸出:

Proxy performs pre-request actions.
Real Subject handles the request.
Proxy performs post-request actions.

Tips:一個代理類,可以代理多個真實角色,并且真實角色之間允許有耦合關系。

普通代理 & 強制代理

在代理模式中,可以區分普通代理和強制代理:

  • 普通代理(Normal Proxy):由代理類控制對真實主題的訪問,客戶端直接與代理類交互,代理類負責將請求轉發給真實主題,調用者只知代理而不用知道真實的角色是誰,屏蔽了真實角色的變更對高層模塊的影響。
  • 強制代理(Force Proxy):“強制”必須通過真實角色查找到代理角色,否則不能訪問。并且只有通過真實角色指定的代理類才可以訪問,也就是說由真實角色管理代理角色。強制代理不需要產生一個代理出來,代理的管理由真實角色自己完成。

上面提供的代碼例子就是普通代理,下面用代碼演示下強制代理:

// 抽象主題接口
public interface Subject {
    /**
     * 待具體實現的方法
     */
    void request();

    /**
     * 獲取每個具體實現對應的代理對象實例
     * @return 返回對應的代理對象
     */
    Subject getProxy();
}


// 強制代理對象
public class ForceProxy implements Subject {

    private Subject subject;

    public ForceProxy(Subject subject) {
        this.subject = subject;
    }

    /**
     * 待具體實現的方法
     */
    @Override
    public void request() {
        preRequest();
        subject.request();
        postRequest();
    }

    /**
     * @return 返回對應的代理對象就是自己
     */
    @Override
    public Subject getProxy() {
        return this;
    }

    private void postRequest() {
        System.out.println("訪問真實主題以后的后續處理");
    }

    private void preRequest() {
        System.out.println("訪問真實主題之前的預處理");
    }
}


// 具體的實現對象
public class RealSubject implements Subject {

    /**
     * 該具體實現對象的代理對象
     */
    private Subject proxy;

    @Override
    public Subject getProxy() {
        proxy = new ForceProxy(this);
        return proxy;
    }

    /**
     * 待具體實現的方法
     */
    @Override
    public void request() {
        if (isProxy()) {
            System.out.println("訪問真實主題方法");
        } else {
            System.out.println("請使用指定的代理訪問");
        }
    }

    private boolean isProxy() {
        return proxy != null;
    }
}

客戶端調用:

public static void main(String[] args) {
        Subject subject = new RealSubject();
        subject.request();
    }
    Output:
    請使用指定的代理訪問
      
      
      
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        Subject proxy = new ForceProxy(subject);
        proxy.request();
    }
    Output:
    訪問真實主題之前的預處理
    請使用指定的代理訪問
    訪問真實主題以后的后續處理
      
      
      
  public static void main(String[] args) {
        Subject subject = new RealSubject();
        Subject proxy = subject.getProxy();
        proxy.request();
    }
    Output:
    訪問真實主題之前的預處理
    訪問真實主題方法
    訪問真實主題以后的后續處理

通過代碼可以觀察到,強制代理模式下,不允許通過真實角色來直接訪問,只有通過真實角色來獲取代理對象,才能訪問。

高層模塊只需調用getProxy就可以訪問真實角色的所有方法,它根本就不需要產生一個代理出來,代理的管理已經由真實角色自己完成。

動態代理

前面講的普通代理和強制代理都屬于靜態代理,也就是說自己寫代理類的方式就是靜態代理。

靜態代理有一個缺點就是要在實現階段就要指定代理類以及被代理者,很不靈活。

而動態代理是一種在運行時動態生成代理類的機制,可以在不預先知道接口的情況下動態創建接口的實現類,允許在運行階段才指定代理哪一個對象,比如Spring AOP就是非常經典的動態代理的應用

下面是兩個動態代理常用的實現方式:

  • JDK 動態代理 :基于 Java 反射機制,在運行時動態創建代理類和對象。JDK 動態代理要求被代理的類實現一個或多個接口,通過 java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler 接口來實現代理對象的生成和方法調用。
  • CGLIB 動態代理:不要求被代理的類實現接口,通過繼承被代理類來生成代理對象。CGLIB 使用字節碼生成庫ASM來動態生成代理類,因此性能略高于 JDK 動態代理。

JDK動態代理

JDK實現動態代理的核心機制就是java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口。

JDK動態代理的動態代理類需要去實現JDK自帶的java.lang.reflect.InvocationHandler接口,該接口中的invoke()方法能夠讓動態代理類實例在運行時調用被代理類需要對外實現的所有接口中的方法,也就是完成對真實主題類方法的調用。

具體實現步驟如下:

  1. 創建一個接口Subject表示被代理的對象需要實現的方法。
  2. 創建一個真實主題類RealSubject,實現Subject接口,定義真正的業務邏輯。
  3. 創建一個實現InvocationHandler接口的代理處理器類DynamicProxyHandler,在invoke方法中執行額外的操作,并調用真實主題的方法。
  4. 在主程序中使用Proxy.newProxyInstance()方法動態生成代理對象,并調用代理對象的方法。

下面是動態代理的示例代碼,一起來感受一下:

// 1. 創建接口
public interface Subject {
    void request();
}

// 2. 創建真實主題類
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject handles the request.");
    }
}

// 3. 創建代理處理器類
public class DynamicProxyHandler implements InvocationHandler {
    private Object target;

    DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 執行額外操作
        System.out.println("Before requesting...");
        
        // 調用真實主題對象的方法
        Object result = method.invoke(target, args);
        
        // 執行額外操作
        System.out.println("After requesting...");
        
        return result;
    }
}

public class DynamicProxyExample {

    public static void main(String[] args) {
        // 創建真實主題對象
        Subject realSubject = new RealSubject();

        // 創建代理處理器對象
        InvocationHandler handler = new DynamicProxyHandler(realSubject);

        // 創建動態代理對象
        Subject proxy = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                handler);

        // 調用代理對象的方法
        proxy.request();
    }
}

這段代碼演示了使用 JDK 動態代理實現動態代理的過程:

  1. 首先,創建了一個真實主題對象 realSubject,表示被代理的真實對象。
  2. 接著,創建了一個代理處理器對象 handler,類型為 InvocationHandler,并將真實主題對象傳入代理處理器中,用于處理代理對象的方法調用。
  3. 然后,通過 Proxy.newProxyInstance() 方法創建了一個動態代理對象 proxy,該方法接受三個參數:
  • 類加載器:使用真實主題對象的類加載器。
  • 接口數組:指定代理對象需要實現的接口,這里使用真實主題對象的接口數組。
  • 處理器:指定代理對象的調用處理器,即前面創建的代理處理器對象 handler。
  1. 最后,通過代理對象 proxy 調用 request() 方法,實際上會委托給代理處理器 handler 的 invoke() 方法來處理方法調用,進而調用真實主題對象的對應方法。

這段代碼通過 JDK 動態代理機制實現了代理對象的動態創建和方法調用處理,實現了對真實主題對象的間接訪問,并在調用真實主題對象方法前后進行了額外的處理。

其動態調用過程如圖所示:

cglib動態代理

JDK的動態代理機制只能代理實現了接口的類,否則不能實現JDK的動態代理,具有一定的局限性。

CGLIB(Code Generation Library)是一個功能強大的字節碼生成庫,可以用來在運行時擴展Java類和實現動態代理。

相對于JDK動態代理基于接口的代理,cglib動態代理基于子類的代理,可以代理那些沒有接口的類,通俗說cglib可以在運行時動態生成字節碼。

cglib的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,因為采用的是繼承,所以不能對final修飾符的類進行代理。

下面是一個使用cglib實現動態代理的示例代碼,包括實現步驟:

  1. 創建一個真實主題類RealSubject,無需實現任何接口。
  2. 創建一個實現MethodInterceptor接口的代理處理器類DynamicProxyHandler,在intercept方法中執行額外的操作,并調用真實主題的方法。
  3. 在主程序中使用Enhancer類創建代理對象,并設置代理處理器。

使用 cglib 需要添加對應的依賴:

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
// 1. 創建真實主題類
public class RealSubject {
    public void request() {
        System.out.println("RealSubject handles the request.");
    }
}

// 2. 創建代理處理器類
public class DynamicProxyHandler implements MethodInterceptor {

    /**
     * 通過Enhancer 創建代理對象
     */
    private Enhancer enhancer = new Enhancer();

    /**
     * 通過class對象獲取代理對象
     * @param clazz class對象
     * @return 代理對象
     */
    public Object getProxy(Class<?> clazz) {
        // 設置需要代理的類
        enhancer.setSuperclass(clazz);
        // 設置enhancer的回調
        enhancer.setCallback(this);
        return enhancer.create();
    }
  
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 執行額外操作
        System.out.println("Before requesting...");

        // 調用真實主題對象的方法
        Object result = proxy.invokeSuper(obj, args);

        // 執行額外操作
        System.out.println("After requesting...");

        return result;
    }
}

public class CglibProxyExample {
    public static void main(String[] args) {
        DynamicProxyHandler proxy = new DynamicProxyHandler();
        RealSubject realSubject = (RealSubject) proxy.getProxy(RealSubject.class);

        // 調用代理對象的方法
        realSubject.request();
    }
}

輸出:

Before requesting...
RealSubject handles the request.
After requesting...

cglib動態代理相比于JDK動態代理的優缺點如下:

優點:

  • 可以代理沒有實現接口的類。
  • 性能更高,因為直接操作字節碼,無需反射。

缺點:

  • 生成的代理類會繼承被代理類,可能會影響某些設計。
  • 無法代理static方法,因為cglib是基于繼承來生成代理類的,而靜態方法是屬于類而非對象的
  • 對于final方法,cglib無法覆蓋,仍然會調用父類方法。

總結

代理模式是一種常用的設計模式,在軟件開發中有著廣泛的應用。通過引入代理對象,可以實現對真實對象的訪問控制、附加功能增強、性能優化等目的。

優點

  • 可以控制對真實對象的訪問,在不改變原始類代碼的情況下擴展其行為。
  • 代理模式能將客戶端與目標對象分離,在一定程序上降低了系統的耦合度.

缺點

  • 增加了系統復雜性,引入了多余的代理類,因此有些類型的代理模式可能會造成請求的處理速度變慢。
  • 實現代理模式需要額外的工作,有些代理模式的實現非常復雜。

總的來說,代理模式通過引入代理對象,實現了對真實對象的間接訪問和控制,為系統的設計提供了一種簡潔而有效的解決方案。在日常的軟件開發中,合理地運用代理模式可以為系統帶來更好的結構和性能表現。

責任編輯:武曉燕 來源: Java隨想錄
相關推薦

2024-01-29 12:22:07

設計模式策略模式

2024-02-19 13:11:38

門面模式系統

2024-02-27 11:59:12

享元模式對象

2024-02-04 12:04:17

2023-05-22 13:27:17

2024-02-21 12:24:33

模板設計模式框架

2024-01-30 13:15:00

設計模式責任鏈

2024-02-23 12:11:53

裝飾器模式對象

2024-02-20 12:09:32

模式工廠方法接口

2024-02-18 12:36:09

2024-02-22 12:13:49

適配器模式代碼

2022-05-05 16:47:24

Docker網絡空間容器

2022-09-21 16:56:16

設計模式微服務架構

2024-04-12 12:19:08

語言模型AI

2022-03-24 08:51:48

Redis互聯網NoSQL

2020-11-17 09:32:57

設計模式責任鏈

2020-11-10 09:20:40

開發模式代碼

2024-06-26 10:29:02

商品中心設計生成器

2023-09-08 08:20:46

ThreadLoca多線程工具

2023-09-15 12:00:01

API應用程序接口
點贊
收藏

51CTO技術棧公眾號

狠狠色综合日日| 国产一二三四区在线观看| 免费看a级黄色片| 日本成人一区二区| 久久影视一区二区| 亚洲一区二区久久久久久| 国产九九在线| 国产成人综合亚洲网站| 欧美大片免费观看| 3d成人动漫在线| 97精品超碰一区二区三区| 欧美日韩在线免费观看| 日韩欧美猛交xxxxx无码| 成人三级视频| 亚洲天堂开心观看| 大胆av不用播放器在线播放| 成人免费视频在线观看| 69精品丰满人妻无码视频a片| 九色精品91| 日韩在线观看成人| 国产91足控脚交在线观看| 亚洲日本在线天堂| 粗暴91大变态调教| 老司机精品视频一区二区三区| 久久久精品2019中文字幕神马| 日本电影在线观看网站| 亚洲午夜私人影院| 国产精品视频免费观看www| 手机看片福利永久国产日韩| 日韩精品免费一区二区三区竹菊| 在线不卡国产精品| 久久青草伊人| 欧美va亚洲va| av观看在线| 亚洲精品久久7777777| 国产剧情在线| 日韩欧美精品在线视频| 免费日本一区二区三区视频| 欧美午夜免费电影| 国产小视频在线观看| 欧美一区在线视频| 蜜桃专区在线| 婷婷国产在线综合| 青青草免费观看免费视频在线| 亚洲国产综合在线| 国产传媒视频在线观看| 亚洲成人动漫一区| 伊人久久青青草| 欧美午夜视频网站| 99爱在线视频| 欧美成人女星排名| av中文字幕在线播放| 日韩精品一区在线| 深夜视频一区二区| 久久99久久亚洲国产| 欧美影院天天5g天天爽| 国产精品尤物福利片在线观看| 一本色道久久| 欧美精品久久96人妻无码| 自拍av一区二区三区| 69国产精品视频| 日韩一区二区视频在线观看| 只有精品亚洲| 99久热re在线精品视频| 97久久精品人人澡人人爽| 成人免费在线电影| 最新69国产成人精品视频免费| 91亚洲一区| 97公开免费视频| 亚洲精品国产品国语在线| 亚洲久久久久| www.久草| 一本一道久久a久久精品逆3p| 爱情电影网av一区二区| 国产 高清 精品 在线 a | 色噜噜狠狠成人网p站| 青青青国内视频在线观看软件| 国产精品视频在线观看| 久久综合久久综合久久| av资源种子在线观看| 日本精品久久久| 久久久精品影视| 亚洲精品乱码日韩| 一区二区av| 色婷婷亚洲一区二区三区| 欧美激情成人| 欧美 日韩精品| 亚洲缚视频在线观看| 极品日韩av| 日本中文字幕视频| 国产精品女人网站| 欧美韩国日本一区| 中文在线最新版地址| 精品日产一区2区三区黄免费| 日本一区二区视频在线| 婷婷午夜社区一区| 欧美精品一区二区三区在线四季| 国内不卡的二区三区中文字幕| 亚洲444eee在线观看| 大陆极品少妇内射aaaaa| 99热这里都是精品| 97视频资源在线观看| 精品999在线观看| 自拍偷拍欧美激情| 亚洲天天影视网| 免费黄色日本网站| 蜜桃一区二区三区| 福利视频久久| 国产精品久久久久av电视剧| 欧美午夜激情在线| 在线播放麻豆| 亚洲777理论| av资源种子在线观看| 久久久另类综合| 天天视频天天爽| 亚洲欧美二区三区| 国产cdts系列另类在线观看| 日韩欧美激情在线| 日本中文字幕一区二区| 777午夜精品福利在线观看| 999在线精品| 日本10禁啪啪无遮挡免费一区二区| 蜜桃视频免费观看一区| 少妇一晚三次一区二区三区| 亚洲永久精品国产| www555久久| 精品中文字幕乱| 影音先锋国产精品| www.亚洲高清| 欧美电影一区二区三区| 国产精品任我爽爆在线播放| 一区二区视频在线播放| 91欧美一区二区| 美女欧美视频在线观看免费 | 国产一级精品在线| 2019国产精品视频| 亚洲另类av| 久久av一区二区三区亚洲| 本田岬高潮一区二区三区| 日本韩国一区| 精品国产电影一区二区| 中文字幕高清在线播放| 91精品在线播放| 丝袜诱惑亚洲看片| www.日本一区| 欧美性猛交xxxx免费看漫画| 亚洲伦乱视频| 国产精品人成电影| 国产精品乱码久久久久久| 日本一区二区三区中文字幕| 欧美一区二区三区四区在线观看地址| 午夜视频在线观看一区| 国产成人三级| 亚洲乱码国产乱码精品天美传媒| 中文字幕视频一区二区三区久| 欧美色图天堂| 午夜精品美女久久久久av福利| 欧美日韩一本到| 亚洲国产福利| 玩弄japan白嫩少妇hd| 精品视频在线播放| 麻豆精品视频在线观看免费| 日韩毛片在线免费看| 欧美成人亚洲成人| 久久午夜免费电影| 另类一区二区三区| 日韩欧美精品久久| 久久亚洲一区二区三区四区| 国产精品xx| a级网站在线观看| 美女av一区二区| 亚洲国产精品影院| 亚洲警察之高压线| 青青草观看免费视频在线| 91av视频在线观看| 久久久欧美精品sm网站| 成人爽a毛片免费啪啪红桃视频| 色琪琪丁香婷婷综合久久| 国产精品久久中文| 色综合天天综合网天天狠天天 | 午夜激情一区| 国产主播福利在线| 欧美大片免费播放| 日韩国产精品视频| 国产欧美日韩亚州综合| 精品三级久久久| 伊人影院蕉久影院在线播放| www.99热.com| 亚洲精品国产suv一区88| 97精品在线观看| 欧美一区二区三区免费观看视频 | 欧美一区二区三区图| 99在线精品一区二区三区| 一区二区三区视频免费观看| 91色在线看| 国产69精品久久久久孕妇| 亚洲熟妇国产熟妇肥婆| 深夜精品寂寞黄网站在线观看| 亚洲精品日日夜夜| 国产麻豆欧美日韩一区|