搜尋
首頁JavaJava入門java代理模式介紹

java代理模式介紹

Jan 27, 2021 am 09:50 AM
java代理模式

java代理模式介紹

我們先來介紹下什麼是代理。

(學習影片分享:java影片教學

代理程式是一種設計模式,它的核心思想,是將對目標的存取轉移到代理物件上。這樣做的好處就是,目標物件在不改變程式碼的情況下,可以透過代理物件加上一些額外的功能。這是一種程式設計思想,在不改變原有程式碼的情況下,透過代理程式增加一些擴充功能。

代理程式如圖所示,使用者存取代理對象,代理對象透過存取目標對象,來達到使用者存取目標對象的目的,

java代理模式介紹

##代理程式模式包含三個角色:

ISubject:介面對象,該介面是對象和它的代理共用的介面。

TargetSubject:目標對象,是實作抽象主題介面的類別。

Proxy:代理角色,內部含有對目標物件TargetSubject的引用,因此可以操作真實物件。代理物件提供與目標物件相同的接口,以便在任何時刻都能取代目標物件。同時,代理物件可以在執行目標物件操作時,附加其他的操作,相當於對真實物件進行封裝。

常見的代理模式分為靜態代理和動態代理,動態代理在Java中的實作分為JDK動態代理和cglib代理。

靜態代理

在之前已經說過,在代理模式中有三個角色,一是目標接口,二是目標對象,三是代理對象。

現在以具體程式碼來實現,首先是目標接口如下:

 public interface IBlogService {

    void writeBlog();
}

目標對象實現了目標接口,程式碼如下:

public class BlogService implements IBlogService {

    @Override
    public void writeBlog() {
        System.out.println("i'm writing...");
    }
}

靜態代理對象,透過建構方法獲取到目標對象,並實現了目標接口,在目標接口的方法裡調用了目標對象的方法,代碼如下:

public class BlogStaticProxy implements IBlogService{
    private IBlogService blogService;

    public BlogStaticProxy(IBlogService blogService) {
        this.blogService = blogService;
    }

    @Override
    public void writeBlog() {
        System.out.println("start writing...");
        blogService.writeBlog();
        System.out.println("end writing...");
    }
}

靜態代理對象,通過構造方法獲取到目標對象,並實現了目標接口,在目標接口的方法裡呼叫了目標對象的方法,代碼如下:

public class BlogStaticProxy implements IBlogService{
    private IBlogService blogService;

    public BlogStaticProxy(IBlogService blogService) {
        this.blogService = blogService;
    }

    @Override
    public void writeBlog() {
        System.out.println("start writing...");
        blogService.writeBlog();
        System.out.println("end writing...");
    }
}

測試:

public class TestStaticProxy {

    public static void main(String[] args) {
        IBlogService target = new BlogService();
        BlogStaticProxy proxy = new BlogStaticProxy(target);
        proxy.write();
    }
}
start writing…
i’m writing…
end writing…

靜態代理,在不修改目標對象的情況下,可以通過代理對象做額外的擴充功能。但靜態方法不是很靈活,如果目標介面的程式碼修改,目標物件和代理物件都需要修改。

動態代理在一定程度上避免這種情況,動態代理不需要代理對象實現目標接口,並且上在java 虛擬機的內存中動態的生成代理對象

Jdk動態對象

Jdk的動態代理由Proxy這個類別來生成,它有三個參數:

ClassLoader loader,:指定目前目標物件使用類別載入器,取得載入器的方法是固定的

Class>[] interfaces,:目標物件實現的介面的類型,使用泛型方式確認類型

#InvocationHandler h:事件處理,執行目標物件的方法時,會觸發事件處理器的方法,會把目前執行目標物件的方法作為參數傳入

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {

    }

Jdk的動態代理程式碼如下:

 public class JdkBlogProxyFactory {

    private Object target;

    public JdkBlogProxyFactory(Object target) {
        this.target = target;
    }

    public Object newInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("start writing");
                    Object o = method.invoke(target, args);
                    System.out.println("end writing");
                    return o;
                });
    }
}

測試類別:

public class TestJdkProxy {
    public static void main(String[] args) {

        IBlogService target = new BlogService();

        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IBlogService proxy = (IBlogService) new JdkBlogProxyFactory(target).newInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.writeBlog();
    }
}

控制台列印如下:

class com.forezp.proxy.BlogService
class com.sun.proxy.$Proxy0
start writing
i&#39;m writing...
end writing

CGLib動態代理

CGLib採用了非常底層的字節碼技術,其原理是透過字節碼技術為一個類別建立子類,並在子類中採用方法攔截的技術攔截所有父類別方法的調用,順勢織入橫切邏輯。

CglibBlogFactory代理工廠類別如下:

public class CglibBlogFactory implements MethodInterceptor {

    private Object target;

    public CglibBlogFactory(Object target) {
        this.target = target;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance() {
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("start writing...");
        //执行目标对象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("end writing...");
        return returnValue;
    }
}

測試類別:

public class TestCglib {

    public static void main(String[] args) {
        IBlogService target = new BlogService();
        //代理对象
        IBlogService proxy = (IBlogService) new CglibBlogFactory(target).getProxyInstance();
        //执行代理对象的方法
        proxy.writeBlog();
    }
}

運行程序,控制台列印:

start writing...
i&#39;m writing...
end writing...

相關推薦:

java入門教學

以上是java代理模式介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金。如有侵權,請聯絡admin@php.cn刪除

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境