文章目錄
- 導讀
- 問題
- CGLib動态代理和JDK動态代理的差別
- CGLib概述
- 改造
導讀
Spring-AOP基礎知識
Java-JDK動态代理
Java-CGLib動态代理
問題
另一篇博文中的問題
性能監視橫切邏輯代碼
CGLib動态代理和JDK動态代理的差別
我們知道使用JDK建立代理時隻能為接口建立代理執行個體。我們從Proxy的newProxyInstance方法中可以看出
@CallerSensitive
public 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();
}
// 攔截父類所有方法的調用
@Override
public 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方法進行代理