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