JDK 代理和 CGLib代理字节码调用实现
JDK
例如我们要增强的是ISendBook接口
JDK 主要依靠反射实现调用
增强类可以看作是一个extends Proxy implements ISendBook的实现类,是Java通过sun.misc.ProxyGenerator#generateProxyClass(java.lang.String, java.lang.Class<?>[], int)方法自己产生了增强类的一个Class对象,
protected final class $Proxy0 extends Proxy implements ISendBook {
// m1 代表equals方法的Method对象
// m2 代表toString方法的Method对象
// m3 代表sendBook方法的
// m0 代表hashCode()
// 在类被加载的时候就加载初始化Method对象
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
// 这个代理对象持有InvocationHandler的引用
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void sendBook() throws {
try {
// 调用SendBookInvocationHandler 增强处理器的invoke方法
//SendBookInvocationHandler内部的invoke 通过反射调用被增强对象的方法。
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("proxy.ISendBook").getMethod("sendBook");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
CGLIB
CGLIb是靠生成字节码来实现调用(例如实现的父类是Customer)
public class Customer {
public void findLove() {
System.out.println("大长腿");
}
}
CGLIb会通过字节码来处理,
他会生成3个类
Customer$$EnhancerByCGLIB$$a1d847ad$$FastClassByCGLIB$$f9a35792 extends FastClass
Customer$$EnhancerByCGLIB$$a1d847ad extends Customer implements Factory
Customer$$FastClassByCGLIB$$18de439e extends FastClass
在实现方面CGLIB通过implements MethodInterceptor
产生的代理对象会extends Customer implements Factory
它实现findLove方法 并且持有增强的引用,findLove()调用增强类CglibMeipo implements MethodInterceptor 的intercept()方法,嵌入增强方法和methodProxy.invokeSuper(o, objects);
// CGLIB$findLove$0$Method 是Method对象
// CGLIB$emptyArgs
// CGLIB$findLove$0$Proxy 是一个MethodProxy
methodInterceptor.intercept(this, CGLIB$findLove$0$Method, CGLIB$emptyArgs, CGLIB$findLove$0$Proxy);
运行的第一次会创建Fast类
这个fast类会根据方法签名返回方法的索引值
Customer$$EnhancerByCGLIB$$a1d847ad$$FastClassByCGLIB$$f9a35792
Fast类
FastClassInfo fci = fastClassInfo;
// fci.i2 :
// obj : Customer$$EnhancerByCGLIB$$a1d847ad
// 通过顺序id switch case 找到对应的入口执行obj的CGLIB$findLove$0();这个方法会调用父类的方法
return fci.f2.invoke(fci.i2, obj, args);