JDK 代理和 CGLib 有什麼區別? 動態代理是一種機制,程式通過該機制在運行時動態生成代理對象並調用代理方法。動態代理主要有兩種實現機制,一種是基於反射動態代理的JDK,另一種是基於ASM動態代理機制的CGLib實現。現在讓我們談談兩種實現之間的區別以及如何實現它們 JDK 代理和 CGLib ...
JDK 代理和 CGLib 有什麼區別?
動態代理是一種機制,程式通過該機制在運行時動態生成代理對象並調用代理方法。動態代理主要有兩種實現機制,一種是基於反射動態代理的JDK,另一種是基於ASM動態代理機制的CGLib實現。現在讓我們談談兩種實現之間的區別以及如何實現它們
JDK 代理和 CGLib 之間的區別
-
JDK動態代理採用反射機制實現,而CGLib基於ASM機制實現,性能不同
-
JDK動態代理是Java語言的內置功能,它不斷更新和升級,沒有任何維護問題。CGLib是基於第三方工具實現的,兩種實現方式往往不同。
-
JDK動態代理必須通過介面實現,調用起來相對簡單,而CGLib不需要介面,調用起來相對複雜。
JDKProxy 動態代理實現
JDK 動態代理通過反射類代理和 InvocationHandler 介面實現。由於JDK中的所有動態代理類都必須實現一個介面,也就是說,動態代理類必須實現在動態代理介面中定義的方法,這會導致反射效率低。
- 代碼實現
public class JdkTokProxyT implements InvocationHandler { private T target; public JdkTikTokProxy(T target) { this.target = target; } public static T T getProxy(T t) { Object o = Proxy.newProxyInstance(t.getClass().getClassLoader() , t.getClass().getInterfaces() , new JdkTikTokProxy(t)); return (T) o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // reflection executes System.out.println("Methods that actually execute the proxied object"); Object invoke = method.invoke(target, args); System.out.println("Return value:" + invoke); return null; }}Copy the code
從上面的代碼中可以看出,JDK 動態代理使用 Proxy 類中的 newProxyInstance 方法創建一個動態代理對象。
newProxyInstance 方法主要採用
參數 | 描述 |
---|---|
類載入器載入器 | 當前用於裝入代理對象的位元組碼的類裝入器。使用與代理對象相同的類裝入器。固定寫入 |
類?[] 介面 | 當前由可執行對象實現的所有介面的位元組碼數組,用於使可執行對象和可執行對象具有相同的方法。固定寫入 |
InvocationHandler h | 目前,當代理對象執行目標方法時,我們可以使用 H 定義攔截增強方法,即我們編寫如何代理。我們通常為此介面編寫一個實現類,通常是匿名內部類,但這不是必需的。 |
invoke 方法的主要功能是通過執行支撐對象的任何介面方法傳遞,或者更確切地說,一個偵聽方法,即調用 main 方法參數
參數 | 描述 |
---|---|
代理 | 對代理對象的引用 |
方法 | 當前執行的方法 |
參數 | 當前執行方法所需的參數 |
返回 | 具有與代理對象相同的返回值 |
invoke() 方法是 JDK 代理的調用介面,它使用 Invocation Invo Invocation。
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
這是因為在動態代理中有一個重要作用,即代理,它用於集中管理prostedobject。顯然,InvoHandler 就是這個代理,invoke() 方法是觸發代理的執行方法。我們通過實現調用介面來獲得動態代理功能。
實施附加
如果使用由 CGLib 實現的動態代理,則不需要代理類來實現介面,這提高了性能,因為 CGLib 使用下麵的 ASM 框架,該框架通過位元組碼技術生成代理類。
動態生成一個支持子類,該子類覆蓋支持類的所有非最終方法。方法攔截攔截子類中對父方法的所有調用,將橫切邏輯編織到子類中,這比Java的反射JDK動態代理更快.
Cglib 是一個功能強大、高性能的代碼生成包,在許多 AOP 框架中廣泛用於提供方法攔截
- 代碼實現如下
public class CglibProxy { public static T T createProxy(T t) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(t.getClass()); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Cglib is on."); Object invoke = proxy.invokeSuper(obj, args); returninvoke; }}); Object o = enhancer.create();return(T) o; }}Copy the code
從上面的代碼中可以看出,CGLib 是基於子類實現的動態代理,並使用增強器類中的 create 方法創建代理對象。因此,代理類不能由關鍵字 final 修改。如果由 final 修改,則在使用增強器設置父類時將報告錯誤,並且無法構建動態代理。