Cglib和jdk動態代理的區別?
a) Jdk動態代理:利用攔截器(必須實現InvocationHandler)加上反射機制生成一個代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理
b) Cglib動態代理:利用ASM框架,對代理對象類生成的class文件加載進來,通過修改其字節碼生成子類來處理
c) 什麼時候用cglib什麼時候用jdk動態代理
i. 目標對象生成了接口 默認用JDK動態代理
ii. 如果目標對象使用了接口,可以強制使用cglib
iii. 如果目標對象沒有實現接口,必須採用cglib庫,Spring會自動在JDK動態代理和cglib之間轉換
d) JDK動態代理和cglib字節碼生成的區別?
i. JDK動態代理只能對實現了接口的類生成代理,而不能針對類
ii. Cglib是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,並覆蓋其中方法的增強,但是因爲採用的是繼承,所以該類或方法最好不要生成final,對於final類或方法,是無法繼承的
e) Cglib比JDK快
i. cglib底層是ASM字節碼生成框架,但是字節碼技術生成代理類,在JDL1.6之前比使用java反射的效率要高
ii. 在jdk6之後逐步對JDK動態代理進行了優化,在調用次數比較少時效率高於cglib代理效率
iii. 只有在大量調用的時候cglib的效率高,但是在1.8的時候JDK的效率已高於cglib
iv. Cglib不能對聲明final的方法進行代理,因爲cglib是動態生成代理對象,final關鍵字修飾的類不可變只能被引用不能被修改
f) Spring如何選擇是用JDK還是cglib
i. 當bean實現接口時,會用JDK代理模式
ii. 當bean沒有實現接口,用cglib實現
iii. 可以強制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
Cglib是什麼?
一. Cglib原理
- 動態生成一個要代理的子類,子類重寫要代理的類的所有不是final的方法。在子類中採用方法攔截技術攔截所有的父類方法的調用,順勢織入橫切邏輯,它比Java反射的jdk動態代理要快
Cglib是一個強大的、高性能的代碼生成包,它被廣泛應用在許多AOP框架中,爲他們提供方法的攔截
最底層的是字節碼Bytecode,字節碼是java爲了保證依次運行,可以跨平臺使用的一種虛擬指令格式
在字節碼文件之上的是ASM,只是一種直接操作字節碼的框架,應用ASM需要對Java字節碼、class結構比較熟悉
位於ASM上面的是Cglib,groovy、beanshell,後來那個種並不是Java體系中的內容是腳本語言,他們通過ASM框架生成字節碼變相執行Java代碼,在JVM中程序執行不一定非要寫java代碼,只要能生成java字節碼,jvm並不關係字節碼的來源
位於cglib、groovy、beanshell之上的就是hibernate和spring AOP
最上面的是applications,既具體應用,一般是一個web項目或者本地跑一個程序、
使用cglib代碼對類做代理?
使用cglib定義不同的攔截策略?
構造函數不攔截方法
用MethodInterceptor和Enhancer實現一個動態代理
Jdk中的動態代理
JDK中的動態代理是通過反射類Proxy以及InvocationHandler回調接口實現的,但是JDK中所有要進行動態代理的類必須要實現一個接口,也就是說只能對該類所實現接口中定義的方法進行代理,這在實際編程中有一定的侷限性,而且使用反射的效率也不高
Cglib實現
使用cglib是實現動態代理,不受代理類必須實現接口的限制,因爲cglib底層是用ASM框架,使用字節碼技術生成代理類,你使用Java反射的效率要高,cglib不能對聲明final的方法進行代理,因爲cglib原理是動態生成被代理類的子類