java動態代理動態在哪裡?

mpsky發表於2021-09-09

最近在學習spring,其中大量使用了動態代理技術來增強Bean的功能。所以有必要捋一捋動態代理。

1、代理

代理是一種經典的設計模式,訪問控制、遠端過程呼叫、AOP都是使用代理的場景。如果對這種設計模式不熟悉,建議參考《Java設計模式》的第11章,裡面也有動態代理的內容。

2、java 的動態代理動態在哪裡?

我們一般建立代理時的順序是:

  • 知道要代理誰,假設為A

  • 建立代理物件,假設為B,繼承A,並讓B持有A的一個例項。

  • 讓B實現與A相同的public方法,在裡面呼叫A對應的方法,此時可以做很多文章,比如打log,驗證引數等,這些行為是我們建立代理的核心目的,畢竟代理不是簡單的傳聲筒。我們暫且將這些行為稱為代理目的

動態代理是反過來的,它是首先知道代理目的,據此實現一個類H,將代理目的的相關程式碼寫進去。這個類H要有一個Object 型別的成員,用來表示要代理的物件。用Object,表示可以代理任何物件。
然後,例項化類H,傳入要代理的具體物件,生成h物件,將h物件和要代理原物件哪些public方法的資訊(透過提供介面的方式)一起交給另一個類Proxy,Proxy會根據public方法的資訊和h物件揉和在一起生成一個代理類$Proxy,並同時例項化該類,生成proxy物件,這個proxy就跟我們按照傳統方式手寫的代理物件是一樣的。

可見,所謂動態,在於真正的代理類是在程式執行的時候由Proxy這個牛叉的類生成的。類生成類就是位元組碼生成技術。這個牛叉的類只需要告訴它代理原物件的哪些public方法(透過介面的形式)和具體的代理行為,即h物件,就可以work了。

H其實就是實現java.lang.reflect.InvocationHandler介面的類。該介面的方法invoke就是我們填寫代理目的程式碼的地方。
Proxy類其實就是java.lang.reflect.Proxy。該類有一個靜態方法newProxyInstance,就是接收h物件和要代理原物件哪些pubic方法的地方。

3、侷限性

java動態代理的侷限性在於,我們告訴Proxy要代理哪些方法時,只能透過原物件實現的介面的方式。就是說,原物件那些不是實現介面的public方法,是沒辦法透過這種技術來代理的。所以才有了CGLIB這種技術。

4、沒有例子嗎?

這裡有。
之前推薦的《Java設計模式》中也有。
《深入理解Java虛擬機器》中也有。應該夠了。
本文的目的在於總結自己對於動態代理的理解,嗯,好像達到了。



作者:milter
連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1806/viewspace-2810224/,如需轉載,請註明出處,否則將追究法律責任。

相關文章