中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java結構型設計模式中代理模式怎么使用

發布時間:2022-09-23 09:50:09 來源:億速云 閱讀:130 作者:iii 欄目:開發技術

本篇內容介紹了“Java結構型設計模式中代理模式怎么使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

代理模式

代理模式(Proxy Pattern)屬于結構型模式。

它是指為其他對象提供一種代理以控制對這個對象的訪問。

在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

在代理模式中,創建具有現有對象的對象,以便向外界提供功能接口。

想在訪問一個類時做一些控制的時候就可以是用代理模式。

分類

代理模式屬于結構型模式,分為靜態代理和動態代理。

1.靜態代理:靜態定義代理類

靜態代理需要自己生成代理類

2.動態代理:動態生成代理類

動態代理不用親自去實現,通常使用現成的API即可。目前普遍使用的是JDK自帶的代理與CGLIB提供的類庫。

主要角色

代理模式一般包含三種角色:

1.抽象主題角色(Subject)

抽象主題類的主要職責是聲明真實主題與代理的共同接口方法,該類可以是接口也可以是抽象類

2.真實主題角色(RealSubject)

該類也被稱為被代理類,該類定義了代理所表示的真實對象,是負責執行系統真正的羅輯業務對象

3.代理主題角色(Proxy)

代理主題也被稱為代理類,其內部特有RealSubject的引用,因此具備完全的對RealSubject的代理權。

客戶端調用代理對象的方法,同時也調用被代理對象的方法,但是會在代理對象前后增加一些處理代碼。可以理解為代碼增強,實際上就是在原代碼羅輯前后增加一些代碼邏輯,而使調用者無感知。

作用

1.保護目標對象,將代理對象與真實被調用目標對象分離

2.增強目標對象

3.降低系統耦合性,提升擴展性

靜態代理與動態代理的區別

1.靜態代理只能通過手動完成代理操作,如果被代理類增加了新的方法,代理類需要同步增加,違背開閉原則。

2.動態代理采用在運行時動態生成代碼的方式,取消了對被代理類的擴展限制,遵循開閉原測。

3.若動態代理要對目標類的增強邏輯進行擴展,結合策略模式,只需要新增策略類便可完成,無須修改代理類的代碼。

靜態代理的基本使用

靜態代理需要自己生成代理類

創建抽象主題

public interface ISubject {
    /**
     * 買票
     */
    void buyTickets();
}

創建真實主題

public class RealSubject implements ISubject {
    public void buyTickets() {
        System.out.println("進行買票操作");
    }
}

創建代理主題

public class Proxy implements ISubject {
    private ISubject subject;
    public Proxy(ISubject subject) {
        this.subject = subject;
    }
    public void buyTickets() {
        before();
        subject.buyTickets();
        after();
    }
    public void before() {
        System.out.println("買票前的操作");
    }
    public void after() {
        System.out.println("買票后的操作");
    }
}

客戶端調用

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

買票前的操作
進行買票操作
買票后的操作

JDK動態代理的基本使用

創建抽象主題

public interface IUser {
    /**
     * 購物
     */
    void shopping();
}

創建真實主題

public class User implements IUser{
    @Override
    public void shopping() {
        System.out.println("user shopping....");
    }
}

創建代理主題

public class JDKProxy implements InvocationHandler {
    private Object tarjet;
    public JDKProxy(Object tarjet) {
        this.tarjet = tarjet;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理user,執行shopping()開始...");
        Object oj = method.invoke(tarjet, args);
        System.out.println("代理user,執行shopping()結束...");
        return oj;
    }
}

客戶端調用

    public static void main(String[] args) {
        User user = new User();
        JDKProxy jdkProxy = new JDKProxy(user);
        IUser proxyInstance = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), jdkProxy);
        proxyInstance.shopping();
    }

代理user,執行shopping()開始...
user shopping....
代理user,執行shopping()結束...

小優化

在調用時候,傳入了一推參數,可進一步優化

public class JDKProxy implements InvocationHandler {
    private Object tarjet;
    public Object JDKProxy(Object target){
        this.tarjet = target;
        Class<?> clazz =  target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理user,執行shopping()開始...");
        Object oj = method.invoke(tarjet, args);
        System.out.println("代理user,執行shopping()結束...");
        return oj;
    }
}
    public static void main(String[] args) {
        JDKProxy jdkProxy = new JDKProxy();
        IUser user= (IUser)jdkProxy.JDKProxy(new User());
        user.shopping();
    }

CGLIB動態代理的基本使用

CGLIB動態代理也不需要生成代理類,實現MethodInterceptor 就可以了。

注意:CGLib不能代理final的方法

創建抽象主題

注意:CGLb代理的目標對象不需要實現任何接口,就可以通過動態繼承目標對象實現動態代理。所以此處可以不用創建接口。直接使用真實主題。

public interface IUser {
    public void shopping();
}

創建真實主題

public class User implements IUser{
    @Override
    public void shopping() {
        System.out.println("user shopping....");
    }
}

直接使用真實主題。

public class User {
    public void shopping() {
        System.out.println("user shopping....");
    }
}

創建代理主題

public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理user,執行shopping()開始...");
        Object invokeSuper = methodProxy.invokeSuper(o, objects);
        System.out.println("代理user,執行shopping()結束...");
        return invokeSuper;
    }
}

客戶端調用

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(User.class);
        enhancer.setCallback(cglibProxy);
        IUser iUser = (IUser) enhancer.create();
        iUser.shopping();
    }

小優化

在客戶端調用時,稍顯復雜,可進一步優化

public class CglibProxy implements MethodInterceptor {
    public Object getInstance(Class<?> clazz) throws Exception{
        //相當于Proxy,代理工具類
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理user,執行shopping()開始...");
        Object invokeSuper = methodProxy.invokeSuper(o, objects);
        System.out.println("代理user,執行shopping()結束...");
        return invokeSuper;
    }
}
    public static void main(String[] args) throws Exception {
        IUser user = (IUser) new CglibProxy().getInstance(User.class);
        user.shopping();
    }

CGLIB與JDK動態代理區別

1.執行條件

JDK動態代理實現了被代理對象的接口。CGLb代理的目標對象不需要實現任何接口,它是通過動態繼承目標對象實現動態代理。

2.實現機制

JDK動態代理調用代理方法是由Java內部的反射機制來實現的,需要讀取接口信息。CGLib動態代理是通過FastClass機制來實現的,需要覆蓋父類方法。

3.性能

首先都在運行期生成字節碼。

JDK動態代理的代理邏輯簡單,直接寫Class字節碼,使用反射機制在生成類的過程中比較高效。

CGLib代理實現更復雜,使用ASM框架寫Class字節碼,但是asm在生成類之后的相關執行過程中比較高效。但是可以通過將asm生成的類進行緩存,解決asm生成類過程低效問題。

一句話:CGLib生成代理類比JDK動態代理效率低,但是執行效率比JDK動態代理高。

“Java結構型設計模式中代理模式怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沈阳市| 绥宁县| 元阳县| 永修县| 额尔古纳市| 衡阳市| 高阳县| 庆城县| 嘉善县| 施甸县| 新宁县| 永胜县| 吐鲁番市| 灵山县| 乐清市| 平远县| 合水县| 正镶白旗| 岗巴县| 黔西| 屏边| 涞源县| 澳门| 巴中市| 绵竹市| 灌阳县| 万盛区| 龙口市| 如皋市| 镶黄旗| 镇原县| 南漳县| 克山县| 花莲县| 武鸣县| 五大连池市| 瓦房店市| 德钦县| 浠水县| 曲麻莱县| 靖江市|