CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。生成的代理类会继承被代理类,并重载其所有的方法。使用Cglib代理会生成三个代理类,继承目标类的代理类、继承FastClass的目标类、继承FastClss的代理类。
我们要想了解其原理,先从生成的代理文件入手,看其结构特点。
编写目标类(被代理类)
public class Book {
public void read(){
System.out.println("read");
}
}
自定义方法拦截器
public class MyCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("增强");
Object o1 = methodProxy.invokeSuper(o, objects);
return o1;
}
}
public class CglibTest {
public static void main(String[] args) {
//指定代理文件生成位置
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:");
//通过Cglib
Enhancer enhancer=new Enhancer();
//设置父类类型
enhancer.setSuperclass(Book.class);
//设置回调接口
enhancer.setCallback(new MyCglib());
Book o = (Book) enhancer.create();
o.read();
}
}
运行以上测试用例后,查看生成的类目录,可以看到生成了3个.class字节码代理文件。
代理类:
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class Book$$EnhancerByCGLIB$$7c19c0f5 extends Book implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$read$0$Method;
private static final MethodProxy CGLIB$read$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("proxy.cglib.Book$$EnhancerByCGLIB$$7c19c0f5");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$read$0$Method = ReflectUtils.findMethods(new String[]{"read", "()V"}, (var1 = Class.forName("proxy.cglib.Book")).getDeclaredMethods())[0];
CGLIB$read$0$Proxy = MethodProxy.create(var1, var0, "()V", "read", "CGLIB$read$0");
}
final void CGLIB$read$0() {
super.read();
}
public final void read() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$read$0$Method, CGLIB$emptyArgs, CGLIB$read$0$Proxy);
} else {
super.read();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1080349215:
if (var10000.equals("read()V")) {
return CGLIB$read$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public Book$$EnhancerByCGLIB$$7c19c0f5() {
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) {
Book$$EnhancerByCGLIB$$7c19c0f5 var1 = (Book$$EnhancerByCGLIB$$7c19c0f5)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;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
目标类FastClass:
import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;
public class Book$$FastClassByCGLIB$$236a9cb6 extends FastClass {
public Book$$FastClassByCGLIB$$236a9cb6(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case 1080349215:
if (var10000.equals("read()V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 1;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 2;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 3;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 1;
}
}
}
break;
case 3496342:
if (var1.equals("read")) {
switch(var2.length) {
case 0:
return 0;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 3;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
Book var10000 = (Book)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.read();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
Book var10000 = new Book;
Book var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 3;
}
}
代理类FastClass:
import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.reflect.FastClass;
import proxy.cglib.Book..EnhancerByCGLIB..7c19c0f5;
public class Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900 extends FastClass {
public Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1882565338:
if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
return 18;
}
break;
case -1870561232:
if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
return 14;
}
break;
case -1745842178:
if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 9;
}
break;
case -1641413109:
if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 4;
}
break;
case -1593131472:
if (var10000.equals("CGLIB$read$0()V")) {
return 20;
}
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 15;
}
break;
case -1411842725:
if (var10000.equals("CGLIB$hashCode$3()I")) {
return 19;
}
break;
case -1034266769:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 13;
}
break;
case -1025895669:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 12;
}
break;
case -988317324:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 5;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return 3;
}
break;
case 610042816:
if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 6;
}
break;
case 1080349215:
if (var10000.equals("read()V")) {
return 7;
}
break;
case 1132856532:
if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
return 10;
}
break;
case 1246779367:
if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
return 8;
}
break;
case 1306468936:
if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
return 16;
}
break;
case 1364367423:
if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
return 11;
}
break;
case 1800494055:
if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
return 17;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 0;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 1;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 2;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 1;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 0;
}
}
}
break;
case -1053468136:
if (var1.equals("getCallbacks")) {
switch(var2.length) {
case 0:
return 10;
}
}
break;
case -124978609:
if (var1.equals("CGLIB$equals$1")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 18;
}
}
}
break;
case -60403779:
if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 13;
}
}
}
break;
case -29025555:
if (var1.equals("CGLIB$hashCode$3")) {
switch(var2.length) {
case 0:
return 19;
}
}
break;
case 3496342:
if (var1.equals("read")) {
switch(var2.length) {
case 0:
return 7;
}
}
break;
case 85179481:
if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 12;
}
}
}
break;
case 94756189:
if (var1.equals("clone")) {
switch(var2.length) {
case 0:
return 3;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case 161998109:
if (var1.equals("CGLIB$STATICHOOK1")) {
switch(var2.length) {
case 0:
return 15;
}
}
break;
case 485510949:
if (var1.equals("CGLIB$read$0")) {
switch(var2.length) {
case 0:
return 20;
}
}
break;
case 495524492:
if (var1.equals("setCallbacks")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 9;
}
}
}
break;
case 1154623345:
if (var1.equals("CGLIB$findMethodProxy")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
return 14;
}
}
}
break;
case 1543336189:
if (var1.equals("CGLIB$toString$2")) {
switch(var2.length) {
case 0:
return 16;
}
}
break;
case 1811874389:
if (var1.equals("newInstance")) {
switch(var2.length) {
case 1:
String var10001 = var2[0].getName();
switch(var10001.hashCode()) {
case -1997738671:
if (var10001.equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 4;
}
break;
case 1364160985:
if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
return 6;
}
}
case 2:
default:
break;
case 3:
if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 5;
}
}
}
break;
case 1817099975:
if (var1.equals("setCallback")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("org.springframework.cglib.proxy.Callback")) {
return 8;
}
}
}
break;
case 1905679803:
if (var1.equals("getCallback")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("int")) {
return 11;
}
}
}
break;
case 1951977610:
if (var1.equals("CGLIB$clone$4")) {
switch(var2.length) {
case 0:
return 17;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
7c19c0f5 var10000 = (7c19c0f5)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
return var10000.toString();
case 2:
return new Integer(var10000.hashCode());
case 3:
return var10000.clone();
case 4:
return var10000.newInstance((Callback[])var3[0]);
case 5:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 6:
return var10000.newInstance((Callback)var3[0]);
case 7:
var10000.read();
return null;
case 8:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 9:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 10:
return var10000.getCallbacks();
case 11:
return var10000.getCallback(((Number)var3[0]).intValue());
case 12:
7c19c0f5.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 13:
7c19c0f5.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 14:
return 7c19c0f5.CGLIB$findMethodProxy((Signature)var3[0]);
case 15:
7c19c0f5.CGLIB$STATICHOOK1();
return null;
case 16:
return var10000.CGLIB$toString$2();
case 17:
return var10000.CGLIB$clone$4();
case 18:
return new Boolean(var10000.CGLIB$equals$1(var3[0]));
case 19:
return new Integer(var10000.CGLIB$hashCode$3());
case 20:
var10000.CGLIB$read$0();
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 {
7c19c0f5 var10000 = new 7c19c0f5;
7c19c0f5 var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 20;
}
}
1、我们可以看到代理类中拥有被代理类的所有的方法,在代理类被实例化后后执行静态代码块的内容,会对被代理类的每个方法进行解析,计算出代理类和被代理类方法名称的Signature值,并封装成MethodProxy对象;
创建MethodProxy过程见方法1详解
创建代理类过程见方法4详解
2、在代理类的方法里面会调用我们自定义的方法拦截器,并把代理类对象、方法名称解析对应的MethodProxy、方法对象传递进去,最终由自定义方法拦截器来调用。
3、自定义方法拦截器中的intercept方法,我们可以根据传递进来的MethodProxy决定调用逻辑,如MethodProxy的invokeSuper会调用父类方法。
4、MethodProxy的invokeSuper方法(见方法2详解)会传递代理类对象及其要执行对应方法参数。invokeSuper流程中会生成继承FastClass的被代理类跟代理类共两个.class文件。其中有两个重要的方法getIndex和invoke方法;
5、getIndex方法会根据步骤1中方法名计算出Signature来匹配方法对应的key,根据key去匹配invoke方法决定最终调用哪个方法。这个步骤没有涉及反射也是与JDK动态代理不同的地方。
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
//计算的是被代理类的
proxy.sig1 = new Signature(name1, desc);
//计算的是代理类的
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}
MethodProxy
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
//这个过程会创建类型为代理类跟被代理的FastClass类
init();
//获取init中封装好的信息
FastClassInfo fci = fastClassInfo;
//调用被代理类的方法,传递方法index下标,通过该下标会在FastClass找出对应的方法并执行
return fci.f2.invoke(fci.i2, obj, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " + sig1);
throw ex;
}
}
init(),见方法3详解
private void init() {
/*
* Using a volatile invariant allows us to initialize the FastClass and
* method index pairs atomically.
*
* Double-checked locking is safe with volatile in Java 5. Before 1.5 this
* code could allow fastClassInfo to be instantiated more than once, which
* appears to be benign.
*/
if (fastClassInfo == null) {
synchronized (initLock) {
//判断是否缓存过
if (fastClassInfo == null) {
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
//生成被代理类的FastClass对象
fci.f1 = helper(ci, ci.c1);
//生成代理类的FastClass对象
fci.f2 = helper(ci, ci.c2);
//根据sig值计算出该方法名在被代理类FastClass中对应的下标
fci.i1 = fci.f1.getIndex(sig1);
//根据sig值计算出该方法名在代理类FastClass中对应的下标
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
生成FastClass对象的过程跟生成代理类过程有点类似,这里不做讲解,后面会讲解代理类的创建过程,过程都差不多。
代理类会在我们测试用例中调用enhancer.create()方法时进行创建。
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
//校验callbackTypes、filter是否为空,以及为空时的处理
preValidate();
//通过newInstance方法来创建EnhancerKey对象.KEY_FACTORY对象在测试用例new Enhance流程中会被动态代理创建
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
//开始创建
Object result = super.create(key);
return result;
}
super.create(key),见方法5详解
protected Object create(Object key) {
try {
//获取类加载器
ClassLoader loader = getClassLoader();
//尝试从缓存中获取当前类加载器对应的ClassLoaderData对象
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
//获取不到则创建
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
//创建ClassLoaderData并加入newCache缓存中
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
//生成代理对象
Object obj = data.get(this, getUseCache());
//如果类似是Class对象,则进行实例化
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
}
new ClassLoaderData(loader),见方法6详解
data.get(this, getUseCache()),见方法7详解
这个类比较长,这里我就把比较重要的两个方法进行讲解,这里
protected static class ClassLoaderData {
private final Set<String> reservedClassNames = new HashSet<String>();
/**
* {@link AbstractClassGenerator} here holds "cache key" (e.g. {@link org.springframework.cglib.proxy.Enhancer}
* configuration), and the value is the generated class plus some additional values
* (see {@link #unwrapCachedValue(Object)}.
* The generated classes can be reused as long as their classloader is reachable.
* Note: the only way to access a class is to find it through generatedClasses cache, thus
* the key should not expire as long as the class itself is alive (its classloader is alive).
*/
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
/**
* Note: ClassLoaderData object is stored as a value of {@code WeakHashMap} thus
* this classLoader reference should be weak otherwise it would make classLoader strongly reachable
* and alive forever.
* Reference queue is not required since the cleanup is handled by {@link WeakHashMap}.
*/
private final WeakReference<ClassLoader> classLoader;
private final Predicate uniqueNamePredicate = new Predicate() {
public boolean evaluate(Object name) {
return reservedClassNames.contains(name);
}
};
//这里存的是Function函数,后续步骤中会调用
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference<ClassLoader>(classLoader);
//这里创建的是函数式接口,后续步骤中会调用
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
//创建代理类
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
public ClassLoader getClassLoader() {
return classLoader.get();
}
public void reserveName(String name) {
reservedClassNames.add(name);
}
public Predicate getUniqueNamePredicate() {
return uniqueNamePredicate;
}
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
return gen.generate(ClassLoaderData.this);
}
else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
}
public Object get(AbstractClassGenerator gen, boolean useCache) {
//如果没有使用缓存,则直接调用创建代理类方法
if (!useCache) {
return gen.generate(ClassLoaderData.this);
}
else {
//这里会调用方法6中创建的两个Function函数式类
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
public V get(K key) {
//调用步骤6中GET_KEY函数式类
KK cacheKey = this.keyMapper.apply(key);
//尝试从缓存中获取代理类对象
Object v = this.map.get(cacheKey);
//如果获取不到则创建代理类
return v != null && !(v instanceof FutureTask) ? v : this.createEntry(key, cacheKey, v);
}
this.createEntry(key, cacheKey, v),见方法8详解
protected V createEntry(final K key, KK cacheKey, Object v) {
boolean creator = false;
FutureTask task;
Object result;
if (v != null) {
task = (FutureTask)v;
} else {
//创建线程
task = new FutureTask(new Callable<V>() {
public V call() throws Exception {
//调用方法6中写好的Function函数
return LoadingCache.this.loader.apply(key);
}
});
//将线程加入缓存中
result = this.map.putIfAbsent(cacheKey, task);
if (result == null) {
creator = true;
//开启线程
task.run();
} else {
if (!(result instanceof FutureTask)) {
return result;
}
task = (FutureTask)result;
}
}
try {
result = task.get();
} catch (InterruptedException var9) {
throw new IllegalStateException("Interrupted while loading cache item", var9);
} catch (ExecutionException var10) {
Throwable cause = var10.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
throw new IllegalStateException("Unable to load cache item", cause);
}
if (creator) {
this.map.put(cacheKey, result);
}
return result;
}
LoadingCache.this.loader.apply(key),见方法9详解
调用函数式接口
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
protected Class generate(ClassLoaderData data) {
validate();
//设置代理类名称前缀
if (superclass != null) {
setNamePrefix(superclass.getName());
}
else if (interfaces != null) {
setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
}
return super.generate(data);
}
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
//将当前代理类生成器存入线程中
CURRENT.set(this);
try {
//获取类加载器
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null while trying to define class " +
getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
"Please file an issue at cglib's issue tracker.");
}
synchronized (classLoader) {
//生成代理类名称
String name = generateClassName(data.getUniqueNamePredicate());
//缓存中存入这个名称
data.reserveName(name);
//当前代理类设置了吗
this.setClassName(name);
}
if (attemptLoad) {
try {
//尝试使用类加载器获取代理对象,获取到则返回
gen = classLoader.loadClass(getClassName());
return gen;
}
catch (ClassNotFoundException e) {
// ignore
}
}
//生成代理类字节码流
byte[] b = strategy.generate(this);
//获取字节码代表的代理类名称
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
// SPRING PATCH BEGIN
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
// SPRING PATCH END
}
return gen;
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
finally {
CURRENT.set(save);
}
}
strategy.generate(this),见方法10详解
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = this.getClassVisitor();
this.transform(cg).generateClass(cw);
return this.transform(cw.toByteArray());
}
public void generateClass(ClassVisitor v) throws Exception {
//如果目标类存在则以目标类为父类,否则以Object为父类
Class sc = (superclass == null) ? Object.class : superclass;
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
//获取父类的所有构造函数
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
//去掉private不能被继承的构造函数
filterConstructors(sc, constructors);
// Order is very important: must add superclass, then
// its superclass chain, then each interface and
// its superinterfaces.
//存放代理类的所有方法
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
//获取其父类的所有方法,包括父类的父类... 父类的所有接口包含的方法,过滤掉不能被继承的方法
getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
//所有方法进行修饰符处理
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method) value;
int modifiers = Constants.ACC_FINAL
| (method.getModifiers()
& ~Constants.ACC_ABSTRACT
& ~Constants.ACC_NATIVE
& ~Constants.ACC_SYNCHRONIZED);
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
//创建写日期
ClassEmitter e = new ClassEmitter(v);
if (currentData == null) {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
Type.getType(sc),
(useFactory ?
TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
TypeUtils.getTypes(interfaces)),
Constants.SOURCE_FILE);
}
else {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
null,
new Type[]{FACTORY},
Constants.SOURCE_FILE);
}
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
if (!interceptDuringConstruction) {
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
}
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
if (serialVersionUID != null) {
e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
for (int i = 0; i < callbackTypes.length; i++) {
e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
}
// This is declared private to avoid "public field" pollution
e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
if (currentData == null) {
//写入方法
emitMethods(e, methods, actualMethods);
//写入构造方法
emitConstructors(e, constructorInfo);
}
else {
emitDefaultConstructor(e);
}
//写入回调方法
emitSetThreadCallbacks(e);
//写入静态代理块
emitSetStaticCallbacks(e);
//绑定回调方法
emitBindCallbacks(e);
if (useFactory || currentData != null) {
int[] keys = getCallbackKeys();
emitNewInstanceCallbacks(e);
emitNewInstanceCallback(e);
emitNewInstanceMultiarg(e, constructorInfo);
emitGetCallback(e, keys);
emitSetCallback(e, keys);
emitGetCallbacks(e);
emitSetCallbacks(e);
}
e.end_class();
}
到这里整个代理类创建过程就差不多告一段落了。
Cglib动态代理不需要被代理类实现接口,根据原理我们知道生成的代理类是继承了被代理类,而且其方法调用方法是使用FastClass,这与JDK动态代理的反射有比较大的区别。
JDK和CGLIB动态代理的区别:
JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGLIB代理使用字节码处理框架ASM,对代理对象类的class文件加载进来,通过修改字节码生成子类。
JDK创建代理对象效率较高,执行效率较低;
CGLIB创建代理对象效率较低,执行效率高。
JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不- 能代理final修饰的类。
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
CGLib 必须依赖于CGLib的类库,需要满足以下要求: