這篇文章主要講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的動態代理 與java動態代理的區別
- Java動態代理生成的代理類和目標類是 “兄弟”關係
- cglib動態代理生成的代理類和目標類是 “父子”關係
CGLib的動態代理 與java動態代理的侷限性
- Java動態代理依賴於目標類有實現介面
- cglib動態代依賴於目標類沒有被final關鍵字修飾
尾巴
CGLIb為了提高效能,還用了一種叫做FastClass的方式來直接呼叫一個物件的方法,而不是通過反射。 至於什麼是 FastClass的方式,之後在寫篇文章