1、靜態代理和動態代理的概念:
在我的另一篇博文:Java 靜態代理和動態代理 中有講到,這里就不做贅述了。
JDK動態代理它的好處理是可以為我們生成任何一個接口的代理類,並將需要增強的方法織入到任意目標函數。
但它仍然具有一個局限性,就是只有實現了接口的類,才能為其實現代理。
2、CGLIB
CGLIB解決了動態代理的難題,它通過生成目標類子類的方式來實現來實現代理,而不是接口,規避了接口的局限性。
CGLIB是一個強大的高性能代碼生成包,其在運行時期(非編譯時期)生成被 代理對象的子類,並重寫了被代理對象的所有方法,從而作為代理對象。
要使用CGLIB先要在POM文件中引入
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
1、業務類
public class UserServiceImpl { public void addUser() { System.out.println("=========增加用戶=========="); } }
2、代理類
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class UserCglib implements MethodInterceptor { private Object _obj; public Object getInstance(Object obj) { this._obj = obj; Enhancer enhancer = new Enhancer();
// 設置代理目標 enhancer.setSuperclass(this._obj.getClass()); // 設置回調 enhancer.setCallback(this); //創建代理對象 return enhancer.create(); }
//回調方法 @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("=========執行前=========="); Object result = proxy.invokeSuper(object, args); System.out.println("=========執行后=========="); return result; } }
3、測試類
public class TestCglib { public static void main(String[] args) { UserCglib cglib = new UserCglib(); UserServiceImpl userServiceImpl = (UserServiceImpl) cglib.getInstance(new UserServiceImpl()); userServiceImpl.addUser(); } }
4、測試結果
=========執行前==========
=========增加用戶==========
=========執行后==========
JDK動態代理和CGLIB庫優點和局限:
- JDK動態代理只能對實現了接口的類生成代理,而不能針對類。
- CGLIB是針對類實現代理,對指定的類生成一個子類,覆蓋其中的方法(繼承),對於無法生成子類的類(final類),肯定是沒有辦法生成代理子類的。
注:靜態代理、動態代理、CGlib看上去實現起來復雜,其實Spring AOP已經幫我們封裝好了,我們直接拿來用就可以了。
本文主要是為了了解 AOP 的實現原理(即基於代理)。
注2:CGLIB包的底層是通過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類。
參考:https://juejin.im/post/591d8c8ba22b9d00585007dd