動(dòng)態(tài)代理-Cglib實(shí)現(xiàn)原理
Cglib提供了一種運(yùn)行時(shí)動(dòng)態(tài)增強(qiáng)類(lèi)的功能。基于ASM在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建class庆揩,暴露Callback接口用于對(duì)類(lèi)和方法進(jìn)行增強(qiáng)。通過(guò)Cglib不僅能夠?qū)崿F(xiàn)同JDK Proxy一樣的基于接口和反射調(diào)用的增強(qiáng)類(lèi)鸳碧,同時(shí)也可以基于實(shí)現(xiàn)類(lèi)對(duì)類(lèi)進(jìn)行增強(qiáng)盾鳞,并且可以避免使用反射調(diào)用,而且使用了FastClass模式瞻离,運(yùn)行效率要高于使用反射
知識(shí)導(dǎo)讀
- cglib是在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建類(lèi)的一種實(shí)現(xiàn)腾仅,可以對(duì)目標(biāo)類(lèi)的行為進(jìn)行擴(kuò)展或者覆蓋,不要局限于代理
- cglib對(duì)目標(biāo)類(lèi)的增強(qiáng)主要是在運(yùn)行時(shí)生成目標(biāo)類(lèi)的子類(lèi)實(shí)現(xiàn)的套利。調(diào)用的時(shí)候基于FastClass模式推励,避免反射鹤耍,運(yùn)行速度比JDK proxy生成的快
- cglib代理會(huì)創(chuàng)建3個(gè)class,所以創(chuàng)建速度會(huì)比JDK proxy慢
- cglib也可以同JDK proxy一樣,創(chuàng)建基于接口實(shí)現(xiàn)的增強(qiáng)類(lèi)验辞,調(diào)用基于反射
- cglib動(dòng)態(tài)增強(qiáng)生成子類(lèi)的時(shí)候稿黄,目標(biāo)類(lèi)和目標(biāo)方法不能是final修飾的
- 對(duì)方法的增強(qiáng)是通過(guò)Callback接口實(shí)現(xiàn)的,所以需要實(shí)現(xiàn)的邏輯都在這
- 使用Callback+CallbackFilter實(shí)現(xiàn)對(duì)不同方法實(shí)現(xiàn)不同的增強(qiáng)
- 最常用的Callback實(shí)現(xiàn)MethodInterceptor跌造,理解每個(gè)參數(shù)的含義
- MethodProxy+FastClass實(shí)現(xiàn)原理
使用
創(chuàng)建一個(gè)非final的類(lèi)杆怕,用于被增強(qiáng)
public class MacBookSeller {
private String name;
public MacBookSeller(String name) {
this.name = name;
}
public MacBookSeller() {
this.name = "未知";
}
public void sellComputor(String brand) {
System.out.println("sell the MacBook computor");
}
public String repairComputor(String brand) {
System.out.println("repair the MacBook computor:" + name);
return name;
}
}
來(lái)看個(gè)使用cglib對(duì)MacBookSeller類(lèi)進(jìn)行增強(qiáng)的例子
public static void main(String[] args) {
//生成cglib生成的類(lèi)
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, JdkProxy.class.getResource("/").getPath());
//創(chuàng)建一個(gè)加強(qiáng)器 Enhancer對(duì)象
Enhancer enhancer = new Enhancer();
//設(shè)置要?jiǎng)?chuàng)建動(dòng)態(tài)代理的類(lèi),即父類(lèi)
enhancer.setSuperclass(MacBookSeller.class);
MacBookSeller macBookSeller = new MacBookSeller("蘋(píng)果專(zhuān)賣(mài)店");
// 設(shè)置回調(diào),這里相當(dāng)于是對(duì)于目標(biāo)類(lèi)上所有方法的調(diào)用壳贪,都會(huì)調(diào)用CallBack陵珍,而Callback則需要實(shí)行intercept()方法進(jìn)行攔截
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if (method.getName().equalsIgnoreCase("repairComputor")) {
System.out.println("開(kāi)始代理");
System.out.println(String.format("method name:%s,args:%s", method.getName(), JSON.toJSONString(args)));
//增強(qiáng)類(lèi)繼承的目標(biāo)類(lèi),調(diào)用父類(lèi)的原方法
Object o = proxy.invokeSuper(obj, args);//通過(guò)增強(qiáng)類(lèi)調(diào)用目標(biāo)類(lèi)方法违施,注意obj是增強(qiáng)類(lèi)對(duì)象
Object o1 = proxy.invoke(macBookSeller, args);//直接通過(guò)父類(lèi)對(duì)象調(diào)用
System.out.println("通過(guò)增強(qiáng)類(lèi)對(duì)象調(diào)用父類(lèi)方法結(jié)果:" + o);//輸出的name是增強(qiáng)類(lèi)的name
System.out.println("通過(guò)目標(biāo)類(lèi)對(duì)象直接調(diào)用目標(biāo)方法結(jié)果:" + o1);//輸出的name是父類(lèi)的name
System.out.println("結(jié)束代理");
return o;//調(diào)用增強(qiáng)類(lèi)對(duì)象方法的返回值
}
return null;
}
});
//創(chuàng)建代理類(lèi)對(duì)象 指定構(gòu)造器
MacBookSeller proxy = MacBookSeller.class.cast(enhancer.create(new Class[]{String.class}, new String[]{"proxy"}));
System.out.println("proxy對(duì)象:" + proxy.getClass().getName());//cn.zlz.proxy.cglib.MacBookSeller$$EnhancerByCGLIB$$9c2b1abb
String result = proxy.repairComputor("mac book pro");
System.out.println("調(diào)用增強(qiáng)類(lèi)對(duì)象的repairComputor方法返回結(jié)果:" + result);
}
Enhancer類(lèi)中也提供了靜態(tài)方法可以直接創(chuàng)建增強(qiáng)類(lèi)對(duì)象
public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) {
Enhancer e = new Enhancer();
e.setSuperclass(superclass);
e.setInterfaces(interfaces);
e.setCallbackFilter(filter);
e.setCallbacks(callbacks);
return e.create();
}
當(dāng)要增強(qiáng)類(lèi)中的不同方法需要不同的增強(qiáng)處理互纯,可以指定多個(gè)Callback實(shí)現(xiàn),同時(shí)使用CallbackFilter來(lái)給不同的方法分配不同的Callback來(lái)進(jìn)行增強(qiáng)
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, JdkProxy.class.getResource("/").getPath());
//創(chuàng)建一個(gè)加強(qiáng)器 Enhancer對(duì)象
Enhancer enhancer = new Enhancer();
//設(shè)置要?jiǎng)?chuàng)建動(dòng)態(tài)代理的類(lèi),即父類(lèi)
enhancer.setSuperclass(MacBookSeller.class);
MethodInterceptor methodInterceptor1 = new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("開(kāi)始代理1");
//代理類(lèi)是繼承的被代理類(lèi)磕蒲,調(diào)用父類(lèi)的原方法
Object o = proxy.invokeSuper(obj, args);
System.out.println(String.format("被代理方法返回值0:%s", o));
System.out.println("結(jié)束代理1");
return o;
}
};
MethodInterceptor methodInterceptor2 = new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("開(kāi)始代理2");
//代理類(lèi)是繼承的被代理類(lèi)留潦,調(diào)用父類(lèi)的原方法
Object o = proxy.invokeSuper(obj, args);
System.out.println(String.format("被代理方法返回值0:%s", o));
System.out.println("結(jié)束代理2");
return o;
}
};
// 設(shè)置回調(diào),這里相當(dāng)于是對(duì)于代理類(lèi)上所有方法的調(diào)用辣往,都會(huì)調(diào)用CallBack兔院,而Callback則需要實(shí)行intercept()方法進(jìn)行攔截
Callback[] callbacks = {methodInterceptor1, methodInterceptor2, NoOp.INSTANCE};
enhancer.setCallbacks(callbacks);
//CallbackFilter對(duì)應(yīng)Callbacks中的,用于指定方法使用哪個(gè)Callback
CallbackFilter callbackFilter = new CallbackFilter() {
@Override
public int accept(Method method) {
if (method.getName().equalsIgnoreCase("repairComputor")) {
return 0;//使用數(shù)組中的一個(gè) MethodInterceptor
} else if (method.getName().equalsIgnoreCase("sellComputor")) {
return 1;//使用Callback數(shù)組中的第二個(gè) MethodInterceptor
} else {
return 2;//其他方法使用NoOp不進(jìn)行任何增強(qiáng)
}
}
};
enhancer.setCallbackFilter(callbackFilter);
MacBookSeller proxy = MacBookSeller.class.cast(Enhancer.create(MacBookSeller.class, null, callbackFilter, callbacks));
proxy.repairComputor("mac book pro");
proxy.sellComputor("mac book pro");
}
Cglib不僅可以基于實(shí)現(xiàn)類(lèi)來(lái)進(jìn)行增強(qiáng)站削,同時(shí)也可以實(shí)現(xiàn)JDK的代理秆乳,在Cglib中提供了一個(gè)InvocationHandler接口實(shí)現(xiàn)了Callback接口,通過(guò)設(shè)置一個(gè)InvocationHandler實(shí)現(xiàn)可以創(chuàng)建一個(gè)和JDK代理實(shí)現(xiàn)方式一樣的增強(qiáng)類(lèi)钻哩,調(diào)用是基于反射來(lái)實(shí)現(xiàn)的,來(lái)看下面例子
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, JdkProxy.class.getResource("/").getPath());
//創(chuàng)建一個(gè)加強(qiáng)器 Enhancer對(duì)象
Enhancer enhancer = new Enhancer();
//設(shè)置要?jiǎng)?chuàng)建動(dòng)態(tài)代理接口
enhancer.setInterfaces(new Class[]{IComputorService.class});
Callback invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println(proxy.getClass().getName());
System.out.println("method:" + method.getName());
// return method.invoke(proxy, args);
boolean enhanced = Enhancer.isEnhanced(proxy.getClass());
System.out.println("是否增強(qiáng):"+enhanced);
return null;
}
};
enhancer.setCallbacks(new Callback[]{invocationHandler, NoOp.INSTANCE});
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
//invocationHandler只攔截repairComputor和sellComputor兩個(gè)方法
if(method.getName().equalsIgnoreCase("repairComputor") ||method.getName().equalsIgnoreCase("sellComputor")) {
return 0;
}else {//使用NoOp不對(duì)其他方法進(jìn)行增強(qiáng)
return 1;
}
}
});
//創(chuàng)建代理類(lèi)對(duì)象
IComputorService proxy = IComputorService.class.cast(enhancer.create());
proxy.repairComputor("mac book pro");
}
原理
cglib基于繼承目標(biāo)類(lèi)創(chuàng)建子類(lèi)進(jìn)行增強(qiáng)的時(shí)候肛冶,會(huì)動(dòng)態(tài)創(chuàng)建3個(gè)類(lèi)街氢,一個(gè)是通過(guò)Enhancer創(chuàng)建一個(gè)目標(biāo)類(lèi)的實(shí)現(xiàn)類(lèi),另外兩個(gè)是通過(guò)MethodProxy創(chuàng)建的FastClass睦袖,分別對(duì)應(yīng)增強(qiáng)前的目標(biāo)類(lèi)的FastClass和增強(qiáng)類(lèi)的FastClass珊肃,F(xiàn)astClass用于基于索引訪問(wèn)對(duì)象的方法。首先來(lái)看動(dòng)態(tài)生成的增強(qiáng)類(lèi)
public class MacBookSeller$$EnhancerByCGLIB$$b857906a extends MacBookSeller implements Factory {
private boolean CGLIB$BOUND;
//用于存儲(chǔ)和線程綁定 Callback
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
//Callback 用于對(duì)方法進(jìn)行增強(qiáng)
private static final Callback[] CGLIB$STATIC_CALLBACKS;
//因?yàn)樵谏傻臅r(shí)候傳遞了3個(gè)Callback馅笙,所有會(huì)有3個(gè)
private MethodInterceptor CGLIB$CALLBACK_0;
private MethodInterceptor CGLIB$CALLBACK_1;
private NoOp CGLIB$CALLBACK_2;
private static final Method CGLIB$repairComputor$0$Method;
//對(duì)應(yīng) repairComputor 的MethodProxy
private static final MethodProxy CGLIB$repairComputor$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$sellComputor$1$Method;
//對(duì)應(yīng) sellComputor 的MethodProxy
private static final MethodProxy CGLIB$sellComputor$1$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
Class var0;
ClassLoader var10000 = (var0 = Class.forName("cn.zlz.proxy.cglib.MacBookSeller$$EnhancerByCGLIB$$b857906a")).getClassLoader();
CGLIB$emptyArgs = new Object[0];
//創(chuàng)建MethodProxy
CGLIB$repairComputor$0$Proxy = MethodProxy.create(var10000, (CGLIB$repairComputor$0$Method = Class.forName("cn.zlz.proxy.cglib.MacBookSeller").getDeclaredMethod("repairComputor", Class.forName("java.lang.String"))).getDeclaringClass(), var0, "(Ljava/lang/String;)Ljava/lang/String;", "repairComputor", "CGLIB$repairComputor$0");
//創(chuàng)建MethodProxy
CGLIB$sellComputor$1$Proxy = MethodProxy.create(var10000, (CGLIB$sellComputor$1$Method = Class.forName("cn.zlz.proxy.cglib.MacBookSeller").getDeclaredMethod("sellComputor", Class.forName("java.lang.String"))).getDeclaringClass(), var0, "(Ljava/lang/String;)V", "sellComputor", "CGLIB$sellComputor$1");
}
final String CGLIB$repairComputor$0(String var1) {
//使用子類(lèi)對(duì)象調(diào)用父類(lèi)方法
return super.repairComputor(var1);
}
//調(diào)用增強(qiáng)后的方法
public final String repairComputor(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
//調(diào)用Callback的實(shí)現(xiàn)類(lèi)實(shí)現(xiàn)
return var10000 != null ? (String)var10000.intercept(this, CGLIB$repairComputor$0$Method, new Object[]{var1}, CGLIB$repairComputor$0$Proxy) : super.repairComputor(var1);
}
final void CGLIB$sellComputor$1(String var1) {
super.sellComputor(var1);
}
public final void sellComputor(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_1;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_1;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$sellComputor$1$Method, new Object[]{var1}, CGLIB$sellComputor$1$Proxy);
} else {
super.sellComputor(var1);
}
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -819357441:
if (var10000.equals("repairComputor(Ljava/lang/String;)Ljava/lang/String;")) {
return CGLIB$repairComputor$0$Proxy;
}
break;
case 667760668:
if (var10000.equals("sellComputor(Ljava/lang/String;)V")) {
return CGLIB$sellComputor$1$Proxy;
}
}
return null;
}
public MacBookSeller$$EnhancerByCGLIB$$b857906a(String var1) {
super(var1);
CGLIB$BIND_CALLBACKS(this);
}
public MacBookSeller$$EnhancerByCGLIB$$b857906a() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
MacBookSeller$$EnhancerByCGLIB$$b857906a var1 = (MacBookSeller$$EnhancerByCGLIB$$b857906a)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
Callback[] var10001 = (Callback[])var10000;
var1.CGLIB$CALLBACK_2 = (NoOp)((Callback[])var10000)[2];
var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
MacBookSeller$$EnhancerByCGLIB$$b857906a var10000 = new MacBookSeller$$EnhancerByCGLIB$$b857906a();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
throw new IllegalStateException("More than one callback object required");
}
//創(chuàng)建對(duì)象的時(shí)候要傳入 Callback
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
MacBookSeller$$EnhancerByCGLIB$$b857906a var10000 = new MacBookSeller$$EnhancerByCGLIB$$b857906a;
//基于CallbackFilter配置來(lái)生成的不同方法設(shè)置不同的Callback
switch(var1.length) {
case 0:
var10000.<init>();
break;
case 1:
if (var1[0].getName().equals("java.lang.String")) {
var10000.<init>((String)var2[0]);
break;
}
throw new IllegalArgumentException("Constructor not found");
default:
throw new IllegalArgumentException("Constructor not found");
}
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
Object var10000;
//基于CallbackFilter配置來(lái)生成的不同方法設(shè)置不同的Callback
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
case 1:
var10000 = this.CGLIB$CALLBACK_1;
break;
case 2:
var10000 = this.CGLIB$CALLBACK_2;
break;
default:
var10000 = null;
}
return (Callback)var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
break;
case 1:
this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;
break;
case 2:
this.CGLIB$CALLBACK_2 = (NoOp)var2;
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];
this.CGLIB$CALLBACK_2 = (NoOp)var1[2];
}
static {
CGLIB$STATICHOOK1();
}
}
通過(guò)生成的增強(qiáng)類(lèi)可以分析以下幾點(diǎn)
- 分清增強(qiáng)類(lèi)和增強(qiáng)類(lèi)對(duì)象伦乔,基于增強(qiáng)類(lèi)可以創(chuàng)建很多對(duì)象,每個(gè)對(duì)象可以設(shè)置不同的Callback實(shí)現(xiàn)
- 在創(chuàng)建增強(qiáng)類(lèi)對(duì)象的時(shí)候董习,一定要傳遞Callback實(shí)現(xiàn)烈和,用于對(duì)方法進(jìn)行增強(qiáng)
- 在增強(qiáng)類(lèi)對(duì)象中可以使用增強(qiáng)類(lèi)對(duì)象調(diào)用目標(biāo)類(lèi)對(duì)象
- 對(duì)方法的增強(qiáng)其實(shí)就是調(diào)用Callback實(shí)現(xiàn)類(lèi)的方法,所以要對(duì)方法進(jìn)行增強(qiáng)皿淋,就是在Callback實(shí)現(xiàn)類(lèi)中寫(xiě)增強(qiáng)邏輯
- 對(duì)于每個(gè)要增強(qiáng)的方法都創(chuàng)建了一個(gè)MethodProxy對(duì)象招刹,在調(diào)用Callback的實(shí)現(xiàn)的增強(qiáng)方法時(shí)將這個(gè)方法的MethodProxy對(duì)象傳遞過(guò)去恬试,對(duì)于FastClass模式調(diào)用就是基于MethodProxy實(shí)現(xiàn)的
接下來(lái)看生成的FastClass,我們只看一個(gè)對(duì)應(yīng)目標(biāo)類(lèi)的FastClass就可以疯暑,對(duì)應(yīng)增強(qiáng)類(lèi)的FastClass實(shí)現(xiàn)是類(lèi)似的
public class MacBookSeller$$FastClassByCGLIB$$f1fe2621 extends FastClass {
public MacBookSeller$$FastClassByCGLIB$$f1fe2621(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1725733088:
if (var10000.equals("getClass()Ljava/lang/Class;")) {
return 8;
}
break;
case -1026001249:
if (var10000.equals("wait(JI)V")) {
return 3;
}
break;
case -819357441:
if (var10000.equals("repairComputor(Ljava/lang/String;)Ljava/lang/String;")) {
return 0;
}
break;
case 243996900:
if (var10000.equals("wait(J)V")) {
return 4;
}
break;
case 667760668:
if (var10000.equals("sellComputor(Ljava/lang/String;)V")) {
return 1;
}
break;
case 946854621:
if (var10000.equals("notifyAll()V")) {
return 10;
}
break;
case 1116248544:
if (var10000.equals("wait()V")) {
return 2;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 5;
}
break;
case 1902039948:
if (var10000.equals("notify()V")) {
return 9;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 6;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 7;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1886247170:
if (var1.equals("repairComputor")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 0;
}
}
}
break;
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 6;
}
}
break;
case -1358544445:
if (var1.equals("sellComputor")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 1;
}
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 5;
}
}
}
break;
case -1039689911:
if (var1.equals("notify")) {
switch(var2.length) {
case 0:
return 9;
}
}
break;
case 3641717:
if (var1.equals("wait")) {
switch(var2.length) {
case 0:
return 2;
case 1:
if (var2[0].getName().equals("long")) {
return 4;
}
break;
case 2:
if (var2[0].getName().equals("long") && var2[1].getName().equals("int")) {
return 3;
}
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 7;
}
}
break;
case 1902066072:
if (var1.equals("notifyAll")) {
switch(var2.length) {
case 0:
return 10;
}
}
break;
case 1950568386:
if (var1.equals("getClass")) {
switch(var2.length) {
case 0:
return 8;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 1;
case 1:
if (var1[0].getName().equals("java.lang.String")) {
return 0;
}
default:
return -1;
}
}
//通過(guò)不同的索引index來(lái)找到具體哪個(gè)方法的調(diào)用训柴,避免了反射調(diào)用
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
MacBookSeller var10000 = (MacBookSeller)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return var10000.repairComputor((String)var3[0]);
case 1:
var10000.sellComputor((String)var3[0]);
return null;
case 2:
var10000.wait();
return null;
case 3:
var10000.wait(((Number)var3[0]).longValue(), ((Number)var3[1]).intValue());
return null;
case 4:
var10000.wait(((Number)var3[0]).longValue());
return null;
case 5:
return new Boolean(var10000.equals(var3[0]));
case 6:
return var10000.toString();
case 7:
return new Integer(var10000.hashCode());
case 8:
return var10000.getClass();
case 9:
var10000.notify();
return null;
case 10:
var10000.notifyAll();
return null;
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
MacBookSeller var10000 = new MacBookSeller;
MacBookSeller var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>((String)var2[0]);
return var10000;
case 1:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 10;
}
}
主要來(lái)看invoke方法,在該方法中建立了目標(biāo)類(lèi)方法和index的對(duì)應(yīng)關(guān)系妇拯。這樣在調(diào)用的時(shí)候直接使用index就可以查找到調(diào)用哪個(gè)方法幻馁,避免了反射調(diào)用。
再來(lái)看下是在哪使用FastClass的invoke方法的越锈,來(lái)看下MethodProxy的實(shí)現(xiàn)仗嗦,每個(gè)方法都會(huì)創(chuàng)建一個(gè)MethodProxy對(duì)象,在MethodProxy對(duì)象中會(huì)分別保存對(duì)應(yīng)目標(biāo)類(lèi)的FastClass對(duì)象和該方法對(duì)應(yīng)的index瞪浸,和對(duì)應(yīng)增強(qiáng)類(lèi)的FastClass對(duì)象和該方法對(duì)應(yīng)的index儒将,通過(guò)調(diào)用FastClass的invoke方法實(shí)現(xiàn)對(duì)方法的調(diào)用
public class MethodProxy {
private Signature sig;
private String superName;//父類(lèi)名稱,也就是增強(qiáng)前類(lèi)的名稱
private FastClass f1;//增強(qiáng)前類(lèi)對(duì)應(yīng)生成的FastClass對(duì)象
private FastClass f2;//增強(qiáng)后類(lèi)對(duì)應(yīng)生成的FastClass對(duì)象
private int i1;//增強(qiáng)前類(lèi)的某方法在FastIndex中的索引
private int i2;//增強(qiáng)后類(lèi)的某方法在FastIndex中的索引
//CGLIB$repairComputor$0$Proxy = MethodProxy.create(var10000, Class.forName("cn.zlz.proxy.cglib.MacBookSeller"), Class.forName("cn.zlz.proxy.cglib.MacBookSeller$$EnhancerByCGLIB$$4780b236"), "(Ljava/lang/String;)Ljava/lang/String;", "repairComputor", "CGLIB$repairComputor$0");
public static MethodProxy create(ClassLoader loader, Class c1, Class c2, String desc, String name1, String name2) {
final Signature sig1 = new Signature(name1, desc);
Signature sig2 = new Signature(name2, desc);
FastClass f1 = helper(loader, c1);//生成增強(qiáng)前類(lèi)的FastClass并創(chuàng)建對(duì)象
FastClass f2 = helper(loader, c2);//生成增強(qiáng)后類(lèi)的FastClass并創(chuàng)建對(duì)象
int i1 = f1.getIndex(sig1);//獲取增強(qiáng)前方法的索引
int i2 = f2.getIndex(sig2);//獲取增強(qiáng)后方法的索引
MethodProxy proxy;
if (i1 < 0) {
proxy = new MethodProxy() {
public Object invoke(Object obj, Object[] args) throws Throwable {
throw new IllegalArgumentException("Protected method: " + sig1);
}
};
} else {
proxy = new MethodProxy();
}
proxy.f1 = f1;
proxy.f2 = f2;
proxy.i1 = i1;
proxy.i2 = i2;
proxy.sig = sig1;
proxy.superName = name2;
return proxy;
}
}
使用MethodProxy的invoke方法調(diào)用目標(biāo)類(lèi)的方法,在該方法中會(huì)調(diào)用目標(biāo)類(lèi)對(duì)應(yīng)的FastClass對(duì)象的invoke方法对蒲,通過(guò)索引找到目標(biāo)對(duì)象的具體方法钩蚊,避免反射
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
return f1.invoke(i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
使用MethodProxy的invokeSuper方法調(diào)用增強(qiáng)類(lèi)的方法,在該方法中調(diào)用增強(qiáng)類(lèi)對(duì)象的FastClass對(duì)象的invoke方法,通過(guò)索引找到具體的方法蹈矮,避免反射
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
return f2.invoke(i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
源碼
簡(jiǎn)單了解下cglib增強(qiáng)類(lèi)的實(shí)現(xiàn)
Callback接口
-
首先認(rèn)識(shí)一下Callback接口砰逻,這是cglib中很重要的一個(gè)接口,用于實(shí)現(xiàn)對(duì)方法增強(qiáng)的攔截接口泛鸟。在增強(qiáng)的時(shí)候可以傳遞多個(gè)Callback實(shí)現(xiàn)類(lèi)對(duì)象蝠咆,不過(guò)一個(gè)方法最多應(yīng)用一個(gè)Callback進(jìn)行增強(qiáng)。不同的方法可以使用不同的Callback實(shí)現(xiàn)類(lèi)來(lái)進(jìn)行增強(qiáng)北滥,這個(gè)要結(jié)合CallbackFilter來(lái)實(shí)現(xiàn)
/** @see MethodInterceptor NoOp LazyLoader Dispatcher InvocationHandler FixedValue*/ public interface Callback{}
-
來(lái)看
Callback
的一個(gè)實(shí)現(xiàn)接口MethodInterceptor
,也是最常用的刚操。public interface MethodInterceptor extends Callback { /** * @param obj "this":增強(qiáng)后的類(lèi)對(duì)象 * @param method: 被攔截的方法,增強(qiáng)前的對(duì)象的方法再芋,通過(guò)這個(gè)method可以用反射調(diào)用原方法 * @param args: 調(diào)用方法時(shí)傳遞的參數(shù) * @param proxy: 可以用來(lái)調(diào)用原方法菊霜,也可以調(diào)用增強(qiáng)后的方法,使用fastClass模式調(diào)用(更快) */ public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable; }
- 當(dāng)調(diào)用增強(qiáng)類(lèi)方法的時(shí)候會(huì)轉(zhuǎn)來(lái)調(diào)用
intercept
方法济赎,在該方法中可以調(diào)用目標(biāo)類(lèi)(父類(lèi))的方法鉴逞,也可以重寫(xiě)邏輯 - 通過(guò)
method
可以用反射的方法調(diào)用增強(qiáng)類(lèi)的方法,然后間接調(diào)用目標(biāo)類(lèi)的方法司训,不過(guò)這種方式不推薦构捡,可以使用proxy.invokeSuper()
,避免反射。
- 當(dāng)調(diào)用增強(qiáng)類(lèi)方法的時(shí)候會(huì)轉(zhuǎn)來(lái)調(diào)用
-
cglib也可以實(shí)現(xiàn)基于jdk的代理壳猜,通過(guò)實(shí)現(xiàn)cglib中的InvocationHandler勾徽。實(shí)現(xiàn)方式與JDK的proxy一樣,都是基于Method反射做的
public interface InvocationHandler extends Callback{ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
-
如果對(duì)方法不做任何攔截蓖谢, cglib提供了 一個(gè)
NoOp
的實(shí)現(xiàn)類(lèi)public interface NoOp extends Callback { public static final NoOp INSTANCE = new NoOp() { }; }
CallbackFilter接口
-
一個(gè)Callback會(huì)作用到類(lèi)的所有方法捂蕴,有時(shí)候不同的方法使用不同的增強(qiáng)Callback譬涡,這時(shí)就可以使用CallbackFilter來(lái)控制。在accept方法中返回的數(shù)字要嚴(yán)格對(duì)應(yīng)Callback[]數(shù)組中對(duì)應(yīng)下標(biāo)的Callback實(shí)現(xiàn)類(lèi)對(duì)象啥辨。
enhancer.setCallbacks(new Callback[]{methodInterceptor1, methodInterceptor2, NoOp.INSTANCE}); CallbackFilter callbackFilter = new CallbackFilter() { @Override public int accept(Method method) { //嚴(yán)格對(duì)應(yīng)Callbacks數(shù)組中的下標(biāo)Callback if(method.getName().equalsIgnoreCase("repairComputor")) { return 0;//使用數(shù)組中的一個(gè) MethodInterceptor }else if(method.getName().equalsIgnoreCase("sellComputor")){ return 1; }else{ return 2; } } }; enhancer.setCallbackFilter(callbackFilter);
Factory接口
-
cglib生成的增強(qiáng)類(lèi)都實(shí)現(xiàn)了
Factory
接口涡匀,通過(guò)接口中的newInstance方法創(chuàng)建對(duì)象會(huì)比較快,不需要反射溉知。通過(guò)接口提供的方法可以看出要?jiǎng)?chuàng)建一個(gè)增強(qiáng)類(lèi)對(duì)象必須要傳遞Callback對(duì)象作為參數(shù),用于對(duì)方法進(jìn)行增強(qiáng)public interface Factory { Object newInstance(Callback callback); Object newInstance(Callback[] callbacks); Object newInstance(Class[] types, Object[] args, Callback[] callbacks); Callback getCallback(int index); void setCallback(int index, Callback callback); void setCallbacks(Callback[] callbacks); Callback[] getCallbacks(); }
Enhancer類(lèi)
Enhancer類(lèi)是cglib提供增強(qiáng)功能的入口類(lèi)陨瘩,通過(guò)該類(lèi)可以在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建增強(qiáng)類(lèi)或者增強(qiáng)類(lèi)對(duì)象
-
判斷類(lèi)是否是用Cglib增強(qiáng)后的類(lèi),注意级乍,由于cglib也可增強(qiáng)基于接口實(shí)現(xiàn)的類(lèi)舌劳,所以如果使用cglib的invocationHandler增強(qiáng)后的類(lèi)通過(guò)isEnhanced返回的也是true
public static boolean isEnhanced(Class type) { try { getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME); return true; } catch (NoSuchMethodException e) { return false; } }
-
調(diào)用create方法進(jìn)入增強(qiáng)類(lèi)對(duì)象的創(chuàng)建流程,在該方法中調(diào)用createHelper方法
//基于無(wú)參構(gòu)造器創(chuàng)建增強(qiáng)類(lèi)對(duì)象 public Object create() { classOnly = false; argumentTypes = null; return createHelper(); } //基于有參構(gòu)造器創(chuàng)建增強(qiáng)類(lèi)對(duì)象 public Object create(Class[] argumentTypes, Object[] arguments) { classOnly = false; if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { throw new IllegalArgumentException("Arguments must be non-null and of equal length"); } this.argumentTypes = argumentTypes; this.arguments = arguments; return createHelper(); }
-
在createHelper方法中進(jìn)行了參數(shù)校驗(yàn)玫荣,然后設(shè)置包名甚淡,然后調(diào)用父類(lèi)的create的方法創(chuàng)建增強(qiáng)類(lèi)對(duì)象,注意傳入了一個(gè)cacheKey捅厂,用于避免重復(fù)創(chuàng)建class贯卦,當(dāng)cacheKey一樣的時(shí)候,直接取緩存中的增強(qiáng)類(lèi)來(lái)創(chuàng)建對(duì)象
private Object createHelper() { validate(); if (superclass != null) {//包名 setNamePrefix(superclass.getName()); } else if (interfaces != null) { setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); } return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, ReflectUtils.getNames(interfaces),filter,callbackTypes,useFactory, interceptDuringConstruction, serialVersionUID)); }
-
在父類(lèi)的create方法中完成了增強(qiáng)類(lèi)對(duì)象焙贷。為了避免重復(fù)創(chuàng)建相同的增強(qiáng)類(lèi)撵割,使用到了緩存。使用strategy生成增強(qiáng)類(lèi)字節(jié)碼辙芍,使用的是ASM實(shí)現(xiàn)的啡彬,這里就不詳細(xì)展示生成過(guò)程了。
protected Object create(Object key) { try { Class gen = null; synchronized (source) { ClassLoader loader = getClassLoader(); Map cache2 = null; cache2 = (Map)source.cache.get(loader); if (cache2 == null) { cache2 = new HashMap(); cache2.put(NAME_KEY, new HashSet()); source.cache.put(loader, cache2); } else if (useCache) { //從緩存中獲取增強(qiáng)類(lèi) Reference ref = (Reference)cache2.get(key); gen = (Class) (( ref == null ) ? null : ref.get()); } if (gen == null) { Object save = CURRENT.get(); CURRENT.set(this); try { this.key = key; if (attemptLoad) { try {//用類(lèi)加載嘗試從虛擬機(jī)中加載增強(qiáng)類(lèi)字節(jié)碼故硅,如果生成過(guò)就不用再創(chuàng)建 gen = loader.loadClass(getClassName()); } catch (ClassNotFoundException e) { // ignore } } if (gen == null) { //調(diào)用strategy生成字節(jié)碼 byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); getClassNameCache(loader).add(className); gen = ReflectUtils.defineClass(className, b, loader); } if (useCache) { //將生成的增強(qiáng)類(lèi)添加到緩存中 cache2.put(key, new WeakReference(gen)); } //創(chuàng)建增強(qiáng)類(lèi)對(duì)象 return firstInstance(gen); } finally { CURRENT.set(save); } } } return firstInstance(gen); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } }
-
在創(chuàng)建完增強(qiáng)類(lèi)之后庶灿,就是創(chuàng)建對(duì)象的過(guò)程,設(shè)置classOnly=true可以只生成增強(qiáng)類(lèi)而不生成對(duì)象
protected Object firstInstance(Class type) throws Exception { if (classOnly) { return type; } else { return createUsingReflection(type); } }
-
反射創(chuàng)建增強(qiáng)類(lèi)對(duì)象吃衅,然后給對(duì)象的Callbacks參數(shù)賦值跳仿,通過(guò)Callback實(shí)現(xiàn)對(duì)方法的增強(qiáng)或者覆蓋
private Object createUsingReflection(Class type) { setThreadCallbacks(type, callbacks);//設(shè)置Callback try{ if (argumentTypes != null) {//創(chuàng)建對(duì)象 return ReflectUtils.newInstance(type, argumentTypes, arguments); } else {//創(chuàng)建對(duì)象 return ReflectUtils.newInstance(type); } }finally{ // clear thread callbacks to allow them to be gc'd setThreadCallbacks(type, null); } }
-
通過(guò)反射將Callback參數(shù)賦值到增強(qiáng)類(lèi)對(duì)象中
private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) { // TODO: optimize try { Method setter = getCallbacksSetter(type, methodName); setter.invoke(null, new Object[]{ callbacks }); } catch (NoSuchMethodException e) { //... } }