Java-CGLib动态代理
文章目錄
- 導讀
- 問題
- CGLib動態代理和JDK動態代理的區別
- CGLib概述
- 改造
導讀
Spring-AOP基礎知識
Java-JDK動態代理
Java-CGLib動態代理
問題
另一篇博文中的問題
性能監視橫切邏輯代碼
CGLib動態代理和JDK動態代理的區別
我們知道使用JDK創建代理時只能為接口創建代理實例。我們從Proxy的newProxyInstance方法中可以看出
@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)第二個參數interfaces就是需要代理實例實現的接口列表。
對于沒有通用接口定義業務方法的類,該如何動態創建代理實例呢?
JDK動態代理技術顯然無能為力了,CGLib作為一個替代者,很好地解決了這個問題
CGLib概述
CGLib采用底層的字節碼技術,可以為一個類創建子類,在子類中采用方法攔截的技術攔截所有父類方法的調用并順勢織入橫切邏輯。
改造
代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster
首先在我們的java maven工程中 添加依賴
<!-- https://mvnrepository.com/artifact/cglib/cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>${cglib.version}</version></dependency>使用的版本為 3.2.5
package com.xgj.aop.base.cglib;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 CglibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class clazz) {// 設置需要創建的子類的類enhancer.setSuperclass(clazz);enhancer.setCallback(this);// 通過字節碼動態創建子類實例return enhancer.create();}// 攔截父類所有方法的調用@Overridepublic Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {// 橫切邏輯代碼PerformanceMonitor.begin(obj.getClass().getName() + "."+ method.getName());// 業務邏輯,通過代理類調用父類中的方法Object result = proxy.invokeSuper(obj, args);// 橫切邏輯代碼PerformanceMonitor.end();return result;}}上述代碼,我們通過getProxy(Class clazz)方法為一個類創建動態代理對象,該代理對象通過擴展clazz實現代理。
在這個代理對象中,織入性能監視的橫切邏輯。
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) 是CGLib定義的Interceptor接口方法,它攔截所有目標類方法中的調用。
其中
-
obj表述目標類的實例
-
method為目標類方法的反射對象
-
args為方法的動態入參
-
proxy為代理類的實例
測試類
通過CglibProxy為ForumSerivceImpl類創建代理對象,并測試代理對象的方法
package com.xgj.aop.base.cglib;public class ForumServiceTest {public static void main(String[] args) {CglibProxy cglibProxy = new CglibProxy();// 通過動態生成子類的方式創建代理類ForumServiceImpl forumService = (ForumServiceImpl) cglibProxy.getProxy(ForumServiceImpl.class);// 調用代理類的業務方法forumService.removeTopic(1);forumService.removeForum(2);} }運行結果
通過輸出,可以看到除了兩個業務方法中都織入了性能監控的邏輯外,還發現代理類的名字變成了
com.xgj.aop.base.cglib.ForumServiceImpl$$EnhancerByCGLIB$$2088954a這個特殊的類就是CGLib為ForumServiceImpl動態創建的子類。
注意:由于cglib采用動態創建子類的方式生成代理對象,所以不能對目標類中的final或者private方法進行代理
總結
以上是生活随笔為你收集整理的Java-CGLib动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java-JDK动态代理
- 下一篇: Spring-AOP 通过配置文件实现