spring jdk動態代理、Cglib動態代理和LoadTimeWeaver(LTW)的應用選擇

在Java 語言中,從織入切面的方式上來看,存在三種織入方式:編譯期織入、類加載期織入和運行期織入。編譯期織入是指在Java編譯期,採用特殊的編譯器,將切面織入到Java類中;而類加載期織入則指通過特殊的類加載器,在類字節碼加載到JVM時,織入切面;運行期織入則是採用CGLib工具或JDK動態代理進行切面的織入。 


AspectJ採用編譯期織入和類加載期織入的方式織入切面,是語言級的AOP實現,提供了完備的AOP支持。它用AspectJ語言定義切面,在編譯期或類加載期將切面織入到Java類中。 

 

AspectJ提供了兩種切面織入方式,第一種通過特殊編譯器,在編譯期,將AspectJ語言編寫的切面類織入到Java類中,可以通過一個Ant或Maven任務來完成這個操作;第二種方式是類加載期織入,也簡稱爲LTW(Load Time Weaving)。 

 

如何使用Load Time Weaving?首先,需要通過JVM的-javaagent參數設置LTW的織入器類包,以代理JVM默認的類加載器;第二,LTW織入器需要一個 aop.xml文件,在該文件中指定切面類和需要進行切面織入的目標類。


在做spring項目時,如果代理對象是單例模式,選擇cglib動態代理;如果是prototype模式,選擇jdk動態代理。

一般不會用到Load Time Weaving代理。

但是,一些特殊情況jdk和cglib動態代理也有侷限性,一些特殊情況只能選擇Load Time Weaving代理。


jdk動態代理的侷限:

因爲jdk代理是 基於接口的動態代理技術,由於接口的方法都必然是public的,這就要求實現類的實現方法也必須是public的(不能是 protected、private等),同時不能使用static的修飾符。所以,可以實施jdk動態代理的方法只能使用public或public final修飾符的方法,其他方法不可能被動態代理,相應的也就不能實施AOP增強,換句話,即不能進行spring 增強了。


Cglib動態代理的侷限:

基於Cglib字節碼動態代理是通過擴展被增強類,動態創建其子類的方式進行AOP增強植入的。由於使用final、static、private修飾符的方法不能被子類覆蓋,相應的,這些方法就無法實施AOP增強。


總結:jdk動態代理創建時效率比cglib高,但執行效率比cglib低。所以如果代理對象是單例模式,選擇cglib動態代理;如果是prototype模式,選擇jdk動態代理。

當遇到jdk和cglib代理侷限性無法解決問題時,可以選擇Load Time Weaving代理。


至於,aspectj 的Load Time Weaving技術的效率,沒研究過,請大牛解惑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章