国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java 代理模式與 AOP

jk_v1 / 422人閱讀

摘要:本文首發于作者最近在學,研究了下和代理模式,寫點心得和大家分享下。所以下面來重點分析下代理模式。這里代理模式分為靜態代理和動態代理兩種,我們分別來看下。代理模式,代理,意味著有一方代替另一方完成一件事。

本文首發于 https://jaychen.cc
作者 jaychen

最近在學 Spring,研究了下 AOP 和代理模式,寫點心得和大家分享下。

AOP

先說下AOP,AOP 全稱 Aspect Oriented Programming,面向切面編程,和 OOP 一樣也是一種編程思想。AOP 出現的原因是為了解決 OOP 在處理 侵入性業務上的不足。

那么,什么是侵入性業務?類似日志統計、性能分析等就屬于侵入性業務。本來原本的業務邏輯代碼優雅大氣,正常運行,突然說需要在這段邏輯里面加上性能分析,于是代碼就變成了下面這個樣子

long begin = System.currentTimeMillis(); 

// 原本的業務
doSomething();

long end = System.currentTimeMillis();
long step = end - begin;
System.out.println("執行花費 :" + step);

從上面的代碼看到,性能分析的業務代碼和原本的業務代碼混在了一起,好端端的代碼就這么被糟蹋了。所以,侵入性業務必須有一個更好的解決方案,這個解決方案就是 AOP。

那么,AOP 是如何解決這類問題?

代理模式

通常,我們會使用代理模式來實現 AOP,這就意味著代理模式可以優雅的解決侵入性業務問題。所以下面來重點分析下代理模式。

這個是代理模式的類圖。很多人可能看不懂類圖,但是說實話有時候一圖勝千言,這里稍微解釋下類圖的含義,尤其是類圖中存在的幾種連線符。

矩形代表一個類,矩形內部的信息有:類名,屬性和方法。

虛線 + 三角空心箭頭為 is=a 的關系,表示繼承,所以上圖中 TestSQLPerformance 都實現 IDatabase 接口。

實線 + 箭頭為關聯關系,一般在代碼中以成員變量的形式體現,所以上圖中 Performance 類有一個 TestSQL 的成員變量。

有了類圖,我們可以根據類圖直接寫出代理模式的代碼了。這里代理模式分為靜態代理和動態代理兩種,我們分別來看下。

靜態代理

假設一個場景,我們需要測試一條 sql query 執行所花費的時間。

如果按照普通的方式,代碼邏輯應該如下

long begin = System.currentTimeMillis(); 

query();

long end = System.currentTimeMillis();
long step = end - begin;
System.out.println("執行花費 :" + step);

上面說過了,這種會導致查詢邏輯和性能測試邏輯混淆在一塊,那么來看看使用代理模式是如何解決這個問題的。

代理模式,代理,意味著有一方代替另一方完成一件事。這里,我們會編寫兩個類:TestSQL 為query 執行邏輯,Performance 為性能測試類。這里 Performance 會代替 TestSQL 去執行 query 邏輯。

要想 Performance 能夠代替 TestSQL 執行 query 邏輯,那么這兩個類應該是有血緣關系的,即這兩個必須實現同一個接口。

// 接口
public interface IDatabase {
    void query();
}


public class TestSQL implements IDatabase {

    @Override
    public void query() {
        System.out.println("執行 query。。。。");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


// 代理類
public class PerformanceMonitor implements IDatabase {
    TestSQL sql;

    public PerformanceMonitor(TestSQL sql) {
        this.sql = sql;
    }


    @Override
    public void query() {
        long begin = System.currentTimeMillis();

        // 業務邏輯。
        sql.query();

        long end = System.currentTimeMillis();
        long step = end - begin;
        System.out.println("執行花費 : " + step);
    }
}


// 測試代碼
public class Main {
    public static void main(String[] strings) {
        TestSQL sql = new TestSQL();

        PerformanceMonitor performanceMonitor = new PerformanceMonitor(sql);
        // 由 Performance 代替 testSQL 執行
        performanceMonitor.query();
    }
}

從上面的示例代碼可以分析出來代理模式是如何運作的,這里我們可以很明顯看出代理模式的優越性,TestSQL 的邏輯很純粹,沒有混入其他無關的業務代碼。

動態代理

回顧靜態代理的代碼,發現代理類 Performance 必須實現 IDatabase 接口。如果有很多業務需要用到代理來實現,那么每個業務都需要定義一個代理類,這會導致類迅速膨脹,為了避免這點,Java 提供了動態代理。

為何稱之為動態代理,動態代理底層是使用反射實現的,是在程序運行期間動態的創建接口的實現。在靜態代理中,我們需要在編碼的時候編寫 Performance 類實現 IDatabase 接口。而使用動態代理,我們不必編寫 Performance 實現 IDatabase 接口,而是 JDK 在底層通過反射技術動態創建一個 IDatabase 接口的實現。

使用動態代理需要使用到 InvocationHandlerProxy 這兩個類。

// 代理類,不再實現 IDatabase 接口,而是實現 InvocationHandler 接口
public class Performance implements InvocationHandler {

    private TestSQL sql;

    public Performance(TestSQL sql) {
        this.sql = sql;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long begin = System.currentTimeMillis();

        // method.invoke 實際上就是調用 sql.query()
        Object object = method.invoke(sql, args);

        long end = System.currentTimeMillis();
        long step = end - begin;
        System.out.println("執行花費 :" + step);
        return object;
    }
}



public class Main {
    public static void main(String[] strings) {
        TestSQL sql = new TestSQL();
        Performance performance = new Performance(sql);

        IDatabase proxy = (IDatabase) Proxy.newProxyInstance(
                sql.getClass().getClassLoader(),
                sql.getClass().getInterfaces(),
                performance
        );
        proxy.query();
    }
}

先來看看 newProxyInstance 函數,這個函數的作用就是用來動態創建一個代理對象的類,這個函數需要三個參數:

第一個參數為類加載器,如果不懂是什么玩意,先套著模板寫,等我寫下一篇文章拯救你。

第二個參數為要代理的接口,在這個例子里面就是 IDatabase 接口。

第三個參數為實現 InvocationHandler 接口的對象。

執行 newProxyInstance 之后,Java 會在底層自動生成一個代理類,其代碼大概如下:

public final class $Proxy1 extends Proxy implements IDatabase{
    private InvocationHandler h;

    private $Proxy1(){}

    public $Proxy1(InvocationHandler h){
        this.h = h;
    }

    public void query(){
        ////創建method對象
        Method method = Subject.class.getMethod("query");
        //調用了invoke方法
        h.invoke(this, method, new Object[]{}); 
    }
}

你會發現,這個類很像在靜態代理中的 Performance 類,是的,動態代理其本質是 Java 自動為我們生成了一個 $Proxy1 代理類。在 mian 函數中 newProxyInstance 的返回值就是該類的一個實例。并且,$Proxy1 中的 h 屬性就是 newProxyInstance 的第三個參數。所以,當我們在 main 函數中執行 proxy.query(),實際上是調用 $proxy1#query 方法,進而再調用 Performance#invoke 方法。而在 Performance#invoke 通過 Object object = method.invoke(sql, args); 調用了 TestSQL#query 方法。

回顧上面的流程,理解動態代理的核心在于理解 Java 自動生成的代理類。這里還有一點要說明,JDK 的動態代理有一個不足:它只能為接口創建代理實例。這句話體現在代碼上就是 newProxyInstance 的第二個參數是一個接口數組。為什么會存在這個不足?其實看 $Proxy1 代理類就知道了,這個由 JDK 生成的代理類需要繼承 Proxy 類,而 Java 只支持單繼承,所以就限制了 JDK 的動態代理只能為接口創建代理。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70430.html

相關文章

  • Java設計模式綜合運用(動態代理+Spring AOP)

    摘要:動態代理的核心是接口和類。以上結果說明它生成的代理類為,說明是代理。測試前提實現接口測試類使用接口方式注入代理方式必須以接口方式注入測試配置為,運行結果如下實際校驗邏輯。。。。 本文也同步發布至簡書,地址:https://www.jianshu.com/p/f70... AOP設計模式通常運用在日志,校驗等業務場景,本文將簡單介紹基于Spring的AOP代理模式的運用。 1. 代理模...

    王晗 評論0 收藏0
  • 慕課網_《探秘Spring AOP》學習總結

    時間:2017年09月03日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com 教學源碼:https://github.com/zccodere/s...學習源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 面向切面 課程章節 概覽 AOP使用 AOP原理 AOP開源運用 課程實戰 課程總結 面向切面編程是一種...

    Tony_Zby 評論0 收藏0
  • 漫談代理模式

    摘要:而在模式中角色與角色的接口是相同的透明性。而在模式中與增加新功能相比它更注重通過設置代理人的方式來減輕本人的工作負擔 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 代理模式是在編程中非常常見的設計模式.筆者在面試的過程中也經常會問到相關的問題,但是很多同學答的并不盡人意.在這篇文章中,筆者想和大家聊聊代理模式的應用及一些實踐. Wha...

    neuSnail 評論0 收藏0
  • Spring AOP就是這么簡單啦

    摘要:是一種特殊的增強切面切面由切點和增強通知組成,它既包括了橫切邏輯的定義也包括了連接點的定義。實際上,一個的實現被拆分到多個類中在中聲明切面我們知道注解很方便,但是,要想使用注解的方式使用就必須要有源碼因為我們要 前言 只有光頭才能變強 上一篇已經講解了Spring IOC知識點一網打盡!,這篇主要是講解Spring的AOP模塊~ 之前我已經寫過一篇關于AOP的文章了,那篇把比較重要的知...

    Jacendfeng 評論0 收藏0
  • 面試官:“談談Spring中都用到了那些設計模式?”。

    摘要:會一直完善下去,歡迎建議和指導,同時也歡迎中用到了那些設計模式中用到了那些設計模式這兩個問題,在面試中比較常見。工廠設計模式使用工廠模式可以通過或創建對象。 我自己總結的Java學習的系統知識點以及面試問題,已經開源,目前已經 41k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...

    Astrian 評論0 收藏0

發表評論

0條評論

jk_v1

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<