每天看看新东西,心情也要好上许多
问题
- cglib是如何实现动态代理的
- cglib如何支持类的代理
- cglib和jdk的动态代理有什么区别
使用方式
cglib不属于jdk的一部分,因此要使用需要先引入相应的包,maven依赖如下
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.0</version>
</dependency>
另外因为spring的aop有使用cglib的实现,因此如果项目引入了spring-core包,那么spring-core包下面已经包含了cglib
使用例子
Test.java
public class Test {
    public static void main(String args[]){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(TestCglib.class);
        enhancer.setCallback(new CglibMethodInterceptor());
        TestCglib testCglib = (TestCglib)enhancer.create();
        testCglib.sayBye("asdsd");
    }
}
TestCglib.java
public class TestCglib {
    public String sayHi(String str){
        System.out.println("我是被代理的sayHi方法");
        return str;
    }
    public String sayBye(String str){
        System.out.println("我是被代理的sayBye方法");
        return str;
    }
}
CglibMethodInterceptor.java
public class CglibMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(method.getName()+"执行之前做一些准备工作");
        Object result = methodProxy.invokeSuper(o,objects);
        System.out.println(method.getName()+"执行之后做一些准备的工作");
        return result;
    }
}
实现
和jdk的代理一样,我们先来看看生成的代理类长什么样:
TestCglib$$EnhancerByCGLIB$$8b20fd94.class(代理类)
public class TestCglib$$EnhancerByCGLIB$$8b20fd94 extends TestCglib implements Factory {
    private static final Method CGLIB$sayHi$1$Method;
    private static final MethodProxy CGLIB$sayHi$1$Proxy;
static void CGLIB$STATICHOOK1() {
    Class var0 = Class.forName("TestCglib$$EnhancerByCGLIB$$8b20fd94");
    Class var1;
    Method[] var10000 = ReflectUtils.findMethods(new String[]{"sayBye", "(Ljava/lang/String;)Ljava/lang/String;", "sayHi", "(Ljava/lang/String;)Ljava/lang/String;"}, (var1 = Class.forName("TestCglib")).getDeclaredMethods());
    CGLIB$sayHi$1$Method = var10000[1];
    CGLIB$sayHi$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "sayHi", "CGLIB$sayHi$1");
}
final String CGLIB$sayHi$1(String var1) {
    return super.sayHi(var1);
}
public final String sayHi(String var1) {
    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$sayHi$1$Method, new Object[]{var1}, CGLIB$sayHi$1$Proxy) : super.sayHi(var1);
}
}
TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598(代理类的FastClass类)
public class TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598 extends FastClass {
public TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598(Class var1) {
    super(var1);
}
public int getIndex(Signature var1) {
    String var10000 = var1.toString();
    switch(var10000.hashCode()) {
    case 481426893:
        if (var10000.equals("sayHi(Ljava/lang/String;)Ljava/lang/String;")) {
            return 7;
        }
        break;
    case 2082116023:
        if (var10000.equals("CGLIB$sayHi$1(Ljava/lang/String;)Ljava/lang/String;")) {
            return 11;
        }
    }
    return -1;
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    8b20fd94 var10000 = (8b20fd94)var2;
    int var10001 = var1;
    try {
        switch(var10001) {
        case 7:
            return var10000.sayHi((String)var3[0]);
        case 11:
            return var10000.CGLIB$sayHi$1((String)var3[0]);
        }
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }
    throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
TestCglib$$FastClassByCGLIB$$2f8a820f(原始类的FastClass类)
public class TestCglib$$FastClassByCGLIB$$2f8a820f extends FastClass {
public TestCglib$$FastClassByCGLIB$$2f8a820f(Class var1) {
    super(var1);
}
public int getIndex(Signature var1) {
    String var10000 = var1.toString();
    switch(var10000.hashCode()) {
    case 481426893:
        if (var10000.equals("sayHi(Ljava/lang/String;)Ljava/lang/String;")) {
            return 1;
        }
        break;
    return -1;
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    TestCglib var10000 = (TestCglib)var2;
    int var10001 = var1;
    try {
        switch(var10001) {
        case 1:
            return var10000.sayHi((String)var3[0]);
        }
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }
    throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
可以看到上面一共生成了三个类,为了突出重点我只保留了和sayHi这个方法相关的部分,这三个类的作用如下:
- 代理类
- 代理类的FastClass类
- 原始类的FastClass类
其中FastClass的类的作用是提前将需要执行的类的所有方法排序,为每个方法生成index,后续直接通过index定位方法执行调用,相对反射而言减少了查询方法的步骤。
ps:由实现可见一共有两个fastClass类,分别对应原始类和代理类,其使用场景分别对应MethodProxy(方法代理类)的invoke 和 invokeSuper类,这两个方法的区别是当调用invoke的时候会直接使用原始类来执行方法,而使用invokeSuper时是采用的代理类执行方法
假设我们访问的方法是sayHi,其调用过程用语言描述如下:
- 调用代理类的sayHi方法,代理类中会为每个方法生成一个方法代理类
- 代理类将方法调用转发至拦截器的intercept方法
- 拦截器在intercept方法中调用sayHi的方法代理类的invokeSuper方法
- 方法代理类使用代理类的FastClass类调用代理类的CGLIB$sayHi$1 方法
- 代理类调用super.sayHi()
- 执行原始类的sayHi方法
流程图如下:

结论
Q:cglib是如何实现动态代理的
利用asm在运行时动态生成和注册代理类,代理类采用继承的方式实现原始类的所有接口,并为每个接口实现方法代理,当调用代理类的方法时会先将所有请求转发至拦截器,后在拦截器中调用方法代理,在方法代理中再通过fastclass类回调回代理类
Q:cglib如何支持类的代理
生成的代理类会继承原始类
Q:cglib和jdk的动态代理有什么区别
- cglib 采用继承实现,jdk采用实现接口
- cglib 底层依赖asm,jdk不依赖



















