CGLib 動態代理

我妻禮彌發表於2019-05-04

這篇文章主要講CGLib的一個應用方面——動態代理

CGLib 是什麼

之前我們有講到ASM,但它相當於是 jvm的 “組合語言” 還是太底層,寫起來很麻煩。於是有了CGLib

CGLib 是一個 可以動態修改 .class位元組碼的工具。它基於 ASM,在ASM的基礎上做了封裝,遮蔽了底層細節,並向上提高一些高階的API抽象。

CGLib封裝程度高,簡單、容易上手,因此名氣反而必 ASM 還大。(充分告訴我們,簡單易使用在任何領域都是多麼的重要)

動態代理

cglib 的應用範圍很廣, 動態代理只是其中的一個應用,不要認為 cglib就只能做動態代理。

使用條件

既然是代理,那肯定要涉及

  • 目標類
  • 代理類

而且代理類必須要和目標類是同一個型別!

什麼意思

比如有下面這樣一個方法,它的引數為 HelloWorld 型別

public void hello(HelloWorld helloWorld) {
    return helloWorld.sayHello();
}
複製程式碼

假設你要代理 HelloWorld 類中的 sayHello() 方法,你的代理類叫 HelloWorldProxy。如果HelloWorldProxy 和 HelloWorld 沒有任何關係的話,那麼它無法作為引數傳遞給hello()方法。

所以說 代理類必須要和目標類是同一個型別!

這裡的“同一個型別”指的是

  • 要麼,代理類目標類都實現了同一個介面,他們都屬於同一種型別,即都是該介面的子類。
  • 要麼,代理類繼承自目標類,這也是屬於同一種型別,前提是目標類沒有被 final 關鍵字修飾

從上面可以看到,兩種方式都有限制。

第一種方式,依賴於目標類的介面,如果目標了沒有介面,就無法實現。第二種方式,依賴於目標類沒有被 final 關鍵字修飾

java動態代理技術就是基於第一種方式實現的。而cglib選擇第二種方式,比較一個類沒有介面的情況很多,但被 final 關鍵字修飾的情況很少。

原理

cglib可以在執行時,動態生成一個代理類繼承我們的目標類,並重寫了目標方法。

如下

CGLib 動態代理

動態生成的代理類,在代理方法中 呼叫了父類(目標類)的目標方法,並在呼叫前後做了一些處理。

CGLib的動態代理 與java動態代理的區別

CGLib 動態代理

  • Java動態代理生成的代理類和目標類是 “兄弟”關係
  • cglib動態代理生成的代理類和目標類是 “父子”關係

CGLib的動態代理 與java動態代理的侷限性

  • Java動態代理依賴於目標類有實現介面
  • cglib動態代依賴於目標類沒有被final關鍵字修飾

尾巴

CGLIb為了提高效能,還用了一種叫做FastClass的方式來直接呼叫一個物件的方法,而不是通過反射。 至於什麼是 FastClass的方式,之後在寫篇文章

相關文章