一、CGlib代理原理
在面向對象編程中,代理模式是一種常用的設計模式。它可以在不改變原有對象代碼的前提下,通過新增代理對象,在代理對象中增加一些其他的功能,從而提供更加完整、更加複雜的功能。CGlib代理是基於動態代理的一種實現方式,是Java中常用的代理技術之一。
動態代理和靜態代理最大的區別就在於代理類的生成方式。靜態代理需要人工編寫代理類,而動態代理則可以在運行時動態生成代理類。Java JDK提供了一個Proxy類,可以通過Proxy的工廠方法newProxyInstance動態生成代理對象。
不過JDK提供的動態代理有一個限制,就是只能代理實現了接口的類。如果要代理沒有實現接口的類,就要使用其他的代理技術。而CGlib是一種可以代理類的技術。使用CGlib實現動態代理,本質上是在運行時,通過位元組碼處理框架ASM,動態生成一個被代理類的子類,並覆蓋其中的方法,達到代理的目的。
二、CGlib原理
CGlib,全稱為Code Generation Library,是一個開源的非侵入式的Java位元組碼生成庫。它允許在運行時對位元組碼進行操作,生成新的類,以實現例如AOP之類的功能。
與靜態代理和JDK動態代理不同,CGlib在運行時動態生成被代理類的子類,並重寫其中的方法。因此,對被代理類的方法訪問是通過子類方法訪問的,而不是被代理類方法訪問的。子類方法可以通過調用父類方法實現對被代理類方法的訪問。
CGlib生成子代理類的方式是在內存中構建代理類的所有方法的位元組碼,並將其轉換成class對象,從而實現對被代理類方法的代理。由於CGlib是直接操作class位元組碼實現代理的,因此需要引入ASM位元組碼框架,用於處理Java位元組碼。
三、CGlib底層原理
CGlib底層運用Java位元組碼技術實現代理,下面簡單介紹一下Java位元組碼的執行過程:
一是Java程序源代碼被編譯成Java位元組碼文件(.class文件)。
二是Java虛擬機(JVM)將Java位元組碼文件解釋成機器指令。
三是CPU執行機器指令,進行計算操作。
CGlib底層實現通過ASM技術直接操作位元組碼來完成對代理對象的生成,主要分為以下幾個步驟:
1、確定需要代理的類和方法,生成對應的MethodInterceptor實現類。
public class UserProxy implements MethodInterceptor { private Object target; public UserProxy(Object target) { this.target = target; } public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before method invoke"); Object result = method.invoke(target, args); System.out.println("After method invoke"); return result; } }
2、使用ASM庫加載被代理類的位元組碼,並動態生成代理對象的子類。
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new UserProxy(target)); Object proxy = enhancer.create();
在這個過程中,我們需要在內存中先讀取被代理類的二進制位元組碼文件,然後再解析出類信息,這個時候我們就要使用ASM庫:
ClassReader classReader = new ClassReader(target.getClass().getName()); ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassVisitor classVisitor = new AddFieldAdapter(classWriter, Opcodes.ACC_PUBLIC, "hash", "I"); classReader.accept(classVisitor, ClassReader.SKIP_DEBUG); byte[] data = classWriter.toByteArray();
四、CGlib底層實現原理
底層實現原理主要是通過ASM(a very small and fast Java bytecode manipulation framework)框架來直接操作數據位元組碼。ASM可以直接生成和修改位元組碼,也可以在位元組碼的生成和修改中提供一些幫助和支持。
ASM使用Visitor模式來操作位元組碼,它通過ClassVisitor和MethodVisitor類提供了訪問類層次結構和方法級別元素的途徑。
CGlib實現動態代理的過程如下:
1、創建Enhancer對象。
2、設置父類和回調方法。
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserService.class); enhancer.setCallback(new UserServiceInterceptor());
3、通過Enhancer對象的create()方法生成代理對象。
UserServiceImpl proxyUserService = (UserServiceImpl) enhancer.create();
4、調用代理對象方法。
String username = userSerivceimpl.getUserName();
五、CGlib動態代理原理
CGlib可以創建一個類的子類,並且在子類中採用方法攔截的技術攔截所有父類方法的調用。在攔截器中可以添加一些額外的邏輯。相比Java動態代理,CGlib不要求被代理類必須實現接口,它是基於類代理,對指定的類生成一個子類,並覆蓋其中的方法來實現代理的功能。
在使用CGlib進行代理時,代理類和被代理類構成了繼承關係。代理類繼承被代理類,所以代理類擁有了被代理類的所有屬性和方法,而且可以攔截被代理方法進行增強。
下面是一個CGlib動態代理實現的示例代碼:
public class UserServiceInterceptor implements MethodInterceptor { private UserService userService; public UserServiceInterceptor(UserService userService) { this.userService = userService; } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("begin method..."); Object result = method.invoke(userService, objects); System.out.println("end method..."); return result; } } Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserService.class); enhancer.setCallback(new UserServiceInterceptor(userService)); UserService userServiceProxy = (UserService) enhancer.create();
結束語
CGlib是一種非常常用的代理方式,通過位元組碼的修改,可以實現對被代理對象的增強和功能擴展。在使用CGlib進行代理時,我們需要深入了解其實現原理,靈活運用其底層知識,才能更好地發揮其代理作用。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/307349.html