Error[8]: Undefined offset: 6, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

目录

JDK代理回顾

CGLIB测试代码DEMO

CGLIB 代理class

FastClass

Spring的CGLIB


JDK代理回顾

JDK动态代理的源码

        MyClass myclass = new MyClass();

        // 创建代理对象
        MyInterface o = (MyInterface)Proxy.newProxyInstance(myclass.getClass().getClassLoader(),
                myclass.getClass().getInterfaces(),
                new MyInvocationHandler(myclass));

根据前两个参数,类加载器和接口类, *** 作字节动态创建一个实现了接口类并继承Proxy的$Proxy0.class代理类

public final class $Proxy0 extends Proxy implements MyInterface {
}

此代理类与原对象myclass没有关系,那在调用代理类时如何关联到真正的对象?

Proxy类内部有一个成员变量InvocationHandler h,$Proxy0各个方法内部实际是调用了InvocationHandler来做 *** 作,也就是new 代理对象时传入的第三个参数handler中关联真正的对象,在handler.invoke方法中做增强 *** 作。

    public final void print() throws  {
            super.h.invoke(this, m3, (Object[])null);
    }
CGLIB测试代码DEMO
public class MyClass{
    public void print() {
        System.out.println("主方法啦啦啦啦啦");
        print2();
    }

    public void print2() {
        System.out.println("2222222222222222222");
    }
}


public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("前置 *** 作" + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置 *** 作" + method.getName());
        return result;
    }
}

public class Test {

    public static void main(String[] args) throws Exception {
        // 将产生的代理类class输出到目标文件夹下
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\CglibTest");
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyClass sample = (MyClass) enhancer.create();
        sample.print();
    }
}

执行如下

 这里和JDK代理有区别了,JDK动态代理时原对象方法内部调用另一方法时,是不会被JDK代理从而被拦截到invocationHandler中的。而CGLIB按照输出看起来,对各种姿势的调用都代理了。

CGLIB 代理class

上边代码有一行输出动态产生的class到指定路径,到路径下找到class,粘贴到idea先来看class源码

public class MyClass$$EnhancerByCGLIB$$c614e522 extends MyClass 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;// 设置的MethodInterceptor回调
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$print$0$Method; // 原对象MyClass的print方法
    private static final MethodProxy CGLIB$print$0$Proxy;  //代理对象的print方法
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$print2$1$Method; // 原对象MyClass的print2方法
    private static final MethodProxy CGLIB$print2$1$Proxy;//代理对象的print2方法
    // =================

    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.example.demo.proxy.cglib.MyClass$$EnhancerByCGLIB$$c614e522");
        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$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");

        // 反射获取MyClass的print\print2方法对象Method
        var10000 = ReflectUtils.findMethods(new String[]{"print", "()V", "print2", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.MyClass")).getDeclaredMethods());
        CGLIB$print$0$Method = var10000[0];
        // 针对各方法 创建方法的代理  var1是原对象class, var0则是刚产生的代理对象class
        CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "()V", "print", "CGLIB$print$0");
        CGLIB$print2$1$Method = var10000[1];
        CGLIB$print2$1$Proxy = MethodProxy.create(var1, var0, "()V", "print2", "CGLIB$print2$1");
    }

    final void CGLIB$print$0() {
        super.print();
    }

    public final void print() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print$0$Method, CGLIB$emptyArgs, CGLIB$print$0$Proxy);
        } else {
            super.print();
        }
    }

    final void CGLIB$print2$1() {
        super.print2();
    }

    public final void print2() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print2$1$Method, CGLIB$emptyArgs, CGLIB$print2$1$Proxy);
        } else {
            super.print2();
        }
    }

    // 。。。。删除了equals\toString等Object的方法和代理

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return CGLIB$print2$1$Proxy;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return CGLIB$print$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    public MyClass$$EnhancerByCGLIB$$c614e522() {
        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) {
        MyClass$$EnhancerByCGLIB$$c614e522 var1 = (MyClass$$EnhancerByCGLIB$$c614e522)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522;
        switch(var1.length) {
        case 0:
            var10000.();
            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();
    }
}

创建的三个类

MyClass$$EnhancerByCGLIB$$c614e522.class  MyClass的代理类class,继承自MyClass,继承自MyClass的方法都存在两份,例如print() 和 CGLIB$print$0(),print()中调用MethodInterceptor增强处理,而CGLIB$print$0()则为直接调用MyClass的方法,这也解释了为什么在MyClass中print()调用print2(),两个方法都会被增强,因为代理类对父类的所有方法都重写了,重写后的方法都会走MethodInterceptor。

再看调用代理对象的 *** 作proxy.invokeSuper(obj, args);,proxy是MethodProxy对象,是对方法的代理对象,看源码如下

其中调用了FastClass的invoke方法,而FastClass则是cglib对于jdk反射调用方法效率比较低的优化, 对一个类的方法建立索引,避免了反射调用,来看cglib自动产生的两个FastClass类

FastClass

1、MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367.class

2、MyClass$$FastClassByCGLIB$$7004c485.class

这一组class,是在调用代理方法(MethodProxy.invoke)时动态被创建,在MethodInterceptor中存在两种调用方法MethodProxy.invoke  调用代理对象的对应方法

MethodProxy.invokeSuper 对应第一个FastClass类,对应代理对象类MyClass$$EnhancerByCGLIB$$c614e522,getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

public class MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367 extends FastClass {
    public MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1870561232:
            if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
                return 21;
            }
            break;
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 22;
            }
            break;
        case -1745842178:
            if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1641413109:
            if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 20;
            }
            break;
        case -1411812934:
            if (var10000.equals("CGLIB$hashCode()I")) {
                return 16;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 7;
            }
            break;
        case -1034266769:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case -1025895669:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 8;
            }
            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 -149311009:
            if (var10000.equals("CGLIB$printpublic class MyClass$$FastClassByCGLIB$04c485 extends FastClass {
    public MyClass$$FastClassByCGLIB$04c485(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 1;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 2;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 3;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 4;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 2;
                    }
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 4;
                }
            }
        }

        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 {
        MyClass var10000 = (MyClass)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.print();
                return null;
            case 1:
                var10000.print2();
                return null;
            case 2:
                return new Boolean(var10000.equals(var3[0]));
            case 3:
                return var10000.toString();
            case 4:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}()V")) {
                return 17;
            }
            break;
        case 56317728:
            if (var10000.equals("CGLIB$print2()V")) {
                return 19;
            }
            break;
        case 374345669:
            if (var10000.equals("CGLIB$equals(Ljava/lang/Object;)Z")) {
                return 18;
            }
            break;
        case 610042816:
            if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case 1132856532:
            if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
                return 13;
            }
            break;
        case 1246779367:
            if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
                return 10;
            }
            break;
        case 1364367423:
            if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
                return 12;
            }
            break;
        case 1517819849:
            if (var10000.equals("CGLIB$toString()Ljava/lang/String;")) {
                return 15;
            }
            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;
            }
            break;
        case 2011844968:
            if (var10000.equals("CGLIB$clone()Ljava/lang/Object;")) {
                return 14;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1872765899:
            if (var1.equals("CGLIB$print2")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        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 13;
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 22;
                }
            }
            break;
        case -124978608:
            if (var1.equals("CGLIB$equals")) {
                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 9;
                    }
                }
            }
            break;
        case -29025554:
            if (var1.equals("CGLIB$hashCode")) {
                switch(var2.length) {
                case 0:
                    return 16;
                }
            }
            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 8;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            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 20;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 11;
                    }
                }
            }
            break;
        case 770871766:
            if (var1.equals("CGLIB$print[+++]")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
                        return 21;
                    }
                }
            }
            break;
        case 1543336190:
            if (var1.equals("CGLIB$toString")) {
                switch(var2.length) {
                case 0:
                    return 15;
                }
            }
            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 6;
                        }
                        break;
                    case 1364160985:
                        if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
                            return 4;
                        }
                    }
                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 10;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 12;
                    }
                }
            }
            break;
        case 1951977611:
            if (var1.equals("CGLIB$clone")) {
                switch(var2.length) {
                case 0:
                    return 14;
                }
            }
        }

        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 {
        c614e522 var10000 = (c614e522)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.print();
                return null;
            case 8:
                c614e522.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 9:
                c614e522.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 10:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 11:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 12:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 13:
                return var10000.getCallbacks();
            case 14:
                return var10000.CGLIB$clone();
            case 15:
                return var10000.CGLIB$toString();
            case 16:
                return new Integer(var10000.CGLIB$hashCode());
            case 17:
                var10000.CGLIB$print[+++]();
                return null;
            case 18:
                return new Boolean(var10000.CGLIB$equals(var3[0]));
            case 19:
                var10000.CGLIB$print2();
                return null;
            case 20:
                c614e522.CGLIB$STATICHOOK1();
                return null;
            case 21:
                return c614e522.CGLIB$findMethodProxy((Signature)var3[0]);
            case 22:
                var10000.print2();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}

MethodProxy.invoke 则对应第二个FastClass类,对应源对象类MyClass,同样getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

[+++]
Spring的CGLIB

demo中在print()方法中调用了print2()方法,输出结果来看,两个方法都被代理了,是因为子类代理对象重写了MyClass的print()和print2()方法,子类方法中都会被interceptor拦截。

但是在spring中,我们知道如上的调用方式print2()是不会被代理拦截的,是为什么呢?

查看了spring源码,cglib最终的调用如图,调用的是methodProxy.invoke且传入的是target对象,执行的是源对象的方法,所以print2()才不会被代理

 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 7, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

目录

JDK代理回顾

CGLIB测试代码DEMO

CGLIB 代理class

FastClass

Spring的CGLIB


JDK代理回顾

JDK动态代理的源码

        MyClass myclass = new MyClass();

        // 创建代理对象
        MyInterface o = (MyInterface)Proxy.newProxyInstance(myclass.getClass().getClassLoader(),
                myclass.getClass().getInterfaces(),
                new MyInvocationHandler(myclass));

根据前两个参数,类加载器和接口类, *** 作字节动态创建一个实现了接口类并继承Proxy的$Proxy0.class代理类

public final class $Proxy0 extends Proxy implements MyInterface {
}

此代理类与原对象myclass没有关系,那在调用代理类时如何关联到真正的对象?

Proxy类内部有一个成员变量InvocationHandler h,$Proxy0各个方法内部实际是调用了InvocationHandler来做 *** 作,也就是new 代理对象时传入的第三个参数handler中关联真正的对象,在handler.invoke方法中做增强 *** 作。

    public final void print() throws  {
            super.h.invoke(this, m3, (Object[])null);
    }
CGLIB测试代码DEMO
public class MyClass{
    public void print() {
        System.out.println("主方法啦啦啦啦啦");
        print2();
    }

    public void print2() {
        System.out.println("2222222222222222222");
    }
}


public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("前置 *** 作" + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置 *** 作" + method.getName());
        return result;
    }
}

public class Test {

    public static void main(String[] args) throws Exception {
        // 将产生的代理类class输出到目标文件夹下
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\CglibTest");
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyClass sample = (MyClass) enhancer.create();
        sample.print();
    }
}

执行如下

 这里和JDK代理有区别了,JDK动态代理时原对象方法内部调用另一方法时,是不会被JDK代理从而被拦截到invocationHandler中的。而CGLIB按照输出看起来,对各种姿势的调用都代理了。

CGLIB 代理class

上边代码有一行输出动态产生的class到指定路径,到路径下找到class,粘贴到idea先来看class源码

public class MyClass$$EnhancerByCGLIB$$c614e522 extends MyClass 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;// 设置的MethodInterceptor回调
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$print$0$Method; // 原对象MyClass的print方法
    private static final MethodProxy CGLIB$print$0$Proxy;  //代理对象的print方法
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$print2$1$Method; // 原对象MyClass的print2方法
    private static final MethodProxy CGLIB$print2$1$Proxy;//代理对象的print2方法
    // =================

    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.example.demo.proxy.cglib.MyClass$$EnhancerByCGLIB$$c614e522");
        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$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");

        // 反射获取MyClass的print\print2方法对象Method
        var10000 = ReflectUtils.findMethods(new String[]{"print", "()V", "print2", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.MyClass")).getDeclaredMethods());
        CGLIB$print$0$Method = var10000[0];
        // 针对各方法 创建方法的代理  var1是原对象class, var0则是刚产生的代理对象class
        CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "()V", "print", "CGLIB$print$0");
        CGLIB$print2$1$Method = var10000[1];
        CGLIB$print2$1$Proxy = MethodProxy.create(var1, var0, "()V", "print2", "CGLIB$print2$1");
    }

    final void CGLIB$print$0() {
        super.print();
    }

    public final void print() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print$0$Method, CGLIB$emptyArgs, CGLIB$print$0$Proxy);
        } else {
            super.print();
        }
    }

    final void CGLIB$print2$1() {
        super.print2();
    }

    public final void print2() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print2$1$Method, CGLIB$emptyArgs, CGLIB$print2$1$Proxy);
        } else {
            super.print2();
        }
    }

    // 。。。。删除了equals\toString等Object的方法和代理

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return CGLIB$print2$1$Proxy;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return CGLIB$print$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    public MyClass$$EnhancerByCGLIB$$c614e522() {
        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) {
        MyClass$$EnhancerByCGLIB$$c614e522 var1 = (MyClass$$EnhancerByCGLIB$$c614e522)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522;
        switch(var1.length) {
        case 0:
            var10000.();
            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();
    }
}

创建的三个类

MyClass$$EnhancerByCGLIB$$c614e522.class  MyClass的代理类class,继承自MyClass,继承自MyClass的方法都存在两份,例如print() 和 CGLIB$print$0(),print()中调用MethodInterceptor增强处理,而CGLIB$print$0()则为直接调用MyClass的方法,这也解释了为什么在MyClass中print()调用print2(),两个方法都会被增强,因为代理类对父类的所有方法都重写了,重写后的方法都会走MethodInterceptor。

再看调用代理对象的 *** 作proxy.invokeSuper(obj, args);,proxy是MethodProxy对象,是对方法的代理对象,看源码如下

其中调用了FastClass的invoke方法,而FastClass则是cglib对于jdk反射调用方法效率比较低的优化, 对一个类的方法建立索引,避免了反射调用,来看cglib自动产生的两个FastClass类

FastClass

1、MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367.class

2、MyClass$$FastClassByCGLIB$$7004c485.class

这一组class,是在调用代理方法(MethodProxy.invoke)时动态被创建,在MethodInterceptor中存在两种调用方法MethodProxy.invoke  调用代理对象的对应方法

MethodProxy.invokeSuper 对应第一个FastClass类,对应代理对象类MyClass$$EnhancerByCGLIB$$c614e522,getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

public class MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367 extends FastClass {
    public MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1870561232:
            if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
                return 21;
            }
            break;
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 22;
            }
            break;
        case -1745842178:
            if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1641413109:
            if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 20;
            }
            break;
        case -1411812934:
            if (var10000.equals("CGLIB$hashCode()I")) {
                return 16;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 7;
            }
            break;
        case -1034266769:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case -1025895669:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 8;
            }
            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 -149311009:
            if (var10000.equals("CGLIB$printpublic class MyClass$$FastClassByCGLIB$04c485 extends FastClass {
    public MyClass$$FastClassByCGLIB$04c485(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 1;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 2;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 3;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 4;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 2;
                    }
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 4;
                }
            }
        }

        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 {
        MyClass var10000 = (MyClass)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.print();
                return null;
            case 1:
                var10000.print2();
                return null;
            case 2:
                return new Boolean(var10000.equals(var3[0]));
            case 3:
                return var10000.toString();
            case 4:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}()V")) {
                return 17;
            }
            break;
        case 56317728:
            if (var10000.equals("CGLIB$print2()V")) {
                return 19;
            }
            break;
        case 374345669:
            if (var10000.equals("CGLIB$equals(Ljava/lang/Object;)Z")) {
                return 18;
            }
            break;
        case 610042816:
            if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case 1132856532:
            if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
                return 13;
            }
            break;
        case 1246779367:
            if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
                return 10;
            }
            break;
        case 1364367423:
            if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
                return 12;
            }
            break;
        case 1517819849:
            if (var10000.equals("CGLIB$toString()Ljava/lang/String;")) {
                return 15;
            }
            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;
            }
            break;
        case 2011844968:
            if (var10000.equals("CGLIB$clone()Ljava/lang/Object;")) {
                return 14;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1872765899:
            if (var1.equals("CGLIB$print2")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        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 13;
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 22;
                }
            }
            break;
        case -124978608:
            if (var1.equals("CGLIB$equals")) {
                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 9;
                    }
                }
            }
            break;
        case -29025554:
            if (var1.equals("CGLIB$hashCode")) {
                switch(var2.length) {
                case 0:
                    return 16;
                }
            }
            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 8;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            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 20;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 11;
                    }
                }
            }
            break;
        case 770871766:
            if (var1.equals("CGLIB$print")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
                        return 21;
                    }
                }
            }
            break;
        case 1543336190:
            if (var1.equals("CGLIB$toString")) {
                switch(var2.length) {
                case 0:
                    return 15;
                }
            }
            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 6;
                        }
                        break;
                    case 1364160985:
                        if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
                            return 4;
                        }
                    }
                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 10;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 12;
                    }
                }
            }
            break;
        case 1951977611:
            if (var1.equals("CGLIB$clone")) {
                switch(var2.length) {
                case 0:
                    return 14;
                }
            }
        }

        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 {
        c614e522 var10000 = (c614e522)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.print();
                return null;
            case 8:
                c614e522.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 9:
                c614e522.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 10:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 11:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 12:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 13:
                return var10000.getCallbacks();
            case 14:
                return var10000.CGLIB$clone();
            case 15:
                return var10000.CGLIB$toString();
            case 16:
                return new Integer(var10000.CGLIB$hashCode());
            case 17:
                var10000.CGLIB$print[+++]();
                return null;
            case 18:
                return new Boolean(var10000.CGLIB$equals(var3[0]));
            case 19:
                var10000.CGLIB$print2();
                return null;
            case 20:
                c614e522.CGLIB$STATICHOOK1();
                return null;
            case 21:
                return c614e522.CGLIB$findMethodProxy((Signature)var3[0]);
            case 22:
                var10000.print2();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}

MethodProxy.invoke 则对应第二个FastClass类,对应源对象类MyClass,同样getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

[+++]
Spring的CGLIB

demo中在print()方法中调用了print2()方法,输出结果来看,两个方法都被代理了,是因为子类代理对象重写了MyClass的print()和print2()方法,子类方法中都会被interceptor拦截。

但是在spring中,我们知道如上的调用方式print2()是不会被代理拦截的,是为什么呢?

查看了spring源码,cglib最终的调用如图,调用的是methodProxy.invoke且传入的是target对象,执行的是源对象的方法,所以print2()才不会被代理

 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 8, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

目录

JDK代理回顾

CGLIB测试代码DEMO

CGLIB 代理class

FastClass

Spring的CGLIB


JDK代理回顾

JDK动态代理的源码

        MyClass myclass = new MyClass();

        // 创建代理对象
        MyInterface o = (MyInterface)Proxy.newProxyInstance(myclass.getClass().getClassLoader(),
                myclass.getClass().getInterfaces(),
                new MyInvocationHandler(myclass));

根据前两个参数,类加载器和接口类, *** 作字节动态创建一个实现了接口类并继承Proxy的$Proxy0.class代理类

public final class $Proxy0 extends Proxy implements MyInterface {
}

此代理类与原对象myclass没有关系,那在调用代理类时如何关联到真正的对象?

Proxy类内部有一个成员变量InvocationHandler h,$Proxy0各个方法内部实际是调用了InvocationHandler来做 *** 作,也就是new 代理对象时传入的第三个参数handler中关联真正的对象,在handler.invoke方法中做增强 *** 作。

    public final void print() throws  {
            super.h.invoke(this, m3, (Object[])null);
    }
CGLIB测试代码DEMO
public class MyClass{
    public void print() {
        System.out.println("主方法啦啦啦啦啦");
        print2();
    }

    public void print2() {
        System.out.println("2222222222222222222");
    }
}


public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("前置 *** 作" + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置 *** 作" + method.getName());
        return result;
    }
}

public class Test {

    public static void main(String[] args) throws Exception {
        // 将产生的代理类class输出到目标文件夹下
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\CglibTest");
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyClass sample = (MyClass) enhancer.create();
        sample.print();
    }
}

执行如下

 这里和JDK代理有区别了,JDK动态代理时原对象方法内部调用另一方法时,是不会被JDK代理从而被拦截到invocationHandler中的。而CGLIB按照输出看起来,对各种姿势的调用都代理了。

CGLIB 代理class

上边代码有一行输出动态产生的class到指定路径,到路径下找到class,粘贴到idea先来看class源码

public class MyClass$$EnhancerByCGLIB$$c614e522 extends MyClass 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;// 设置的MethodInterceptor回调
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$print$0$Method; // 原对象MyClass的print方法
    private static final MethodProxy CGLIB$print$0$Proxy;  //代理对象的print方法
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$print2$1$Method; // 原对象MyClass的print2方法
    private static final MethodProxy CGLIB$print2$1$Proxy;//代理对象的print2方法
    // =================

    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.example.demo.proxy.cglib.MyClass$$EnhancerByCGLIB$$c614e522");
        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$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");

        // 反射获取MyClass的print\print2方法对象Method
        var10000 = ReflectUtils.findMethods(new String[]{"print", "()V", "print2", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.MyClass")).getDeclaredMethods());
        CGLIB$print$0$Method = var10000[0];
        // 针对各方法 创建方法的代理  var1是原对象class, var0则是刚产生的代理对象class
        CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "()V", "print", "CGLIB$print$0");
        CGLIB$print2$1$Method = var10000[1];
        CGLIB$print2$1$Proxy = MethodProxy.create(var1, var0, "()V", "print2", "CGLIB$print2$1");
    }

    final void CGLIB$print$0() {
        super.print();
    }

    public final void print() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print$0$Method, CGLIB$emptyArgs, CGLIB$print$0$Proxy);
        } else {
            super.print();
        }
    }

    final void CGLIB$print2$1() {
        super.print2();
    }

    public final void print2() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print2$1$Method, CGLIB$emptyArgs, CGLIB$print2$1$Proxy);
        } else {
            super.print2();
        }
    }

    // 。。。。删除了equals\toString等Object的方法和代理

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return CGLIB$print2$1$Proxy;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return CGLIB$print$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    public MyClass$$EnhancerByCGLIB$$c614e522() {
        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) {
        MyClass$$EnhancerByCGLIB$$c614e522 var1 = (MyClass$$EnhancerByCGLIB$$c614e522)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522;
        switch(var1.length) {
        case 0:
            var10000.();
            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();
    }
}

创建的三个类

MyClass$$EnhancerByCGLIB$$c614e522.class  MyClass的代理类class,继承自MyClass,继承自MyClass的方法都存在两份,例如print() 和 CGLIB$print$0(),print()中调用MethodInterceptor增强处理,而CGLIB$print$0()则为直接调用MyClass的方法,这也解释了为什么在MyClass中print()调用print2(),两个方法都会被增强,因为代理类对父类的所有方法都重写了,重写后的方法都会走MethodInterceptor。

再看调用代理对象的 *** 作proxy.invokeSuper(obj, args);,proxy是MethodProxy对象,是对方法的代理对象,看源码如下

其中调用了FastClass的invoke方法,而FastClass则是cglib对于jdk反射调用方法效率比较低的优化, 对一个类的方法建立索引,避免了反射调用,来看cglib自动产生的两个FastClass类

FastClass

1、MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367.class

2、MyClass$$FastClassByCGLIB$$7004c485.class

这一组class,是在调用代理方法(MethodProxy.invoke)时动态被创建,在MethodInterceptor中存在两种调用方法MethodProxy.invoke  调用代理对象的对应方法

MethodProxy.invokeSuper 对应第一个FastClass类,对应代理对象类MyClass$$EnhancerByCGLIB$$c614e522,getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

public class MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367 extends FastClass {
    public MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1870561232:
            if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
                return 21;
            }
            break;
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 22;
            }
            break;
        case -1745842178:
            if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1641413109:
            if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 20;
            }
            break;
        case -1411812934:
            if (var10000.equals("CGLIB$hashCode()I")) {
                return 16;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 7;
            }
            break;
        case -1034266769:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case -1025895669:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 8;
            }
            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 -149311009:
            if (var10000.equals("CGLIB$printpublic class MyClass$$FastClassByCGLIB$04c485 extends FastClass {
    public MyClass$$FastClassByCGLIB$04c485(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 1;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 2;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 3;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 4;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 2;
                    }
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 4;
                }
            }
        }

        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 {
        MyClass var10000 = (MyClass)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.print();
                return null;
            case 1:
                var10000.print2();
                return null;
            case 2:
                return new Boolean(var10000.equals(var3[0]));
            case 3:
                return var10000.toString();
            case 4:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}()V")) {
                return 17;
            }
            break;
        case 56317728:
            if (var10000.equals("CGLIB$print2()V")) {
                return 19;
            }
            break;
        case 374345669:
            if (var10000.equals("CGLIB$equals(Ljava/lang/Object;)Z")) {
                return 18;
            }
            break;
        case 610042816:
            if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case 1132856532:
            if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
                return 13;
            }
            break;
        case 1246779367:
            if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
                return 10;
            }
            break;
        case 1364367423:
            if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
                return 12;
            }
            break;
        case 1517819849:
            if (var10000.equals("CGLIB$toString()Ljava/lang/String;")) {
                return 15;
            }
            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;
            }
            break;
        case 2011844968:
            if (var10000.equals("CGLIB$clone()Ljava/lang/Object;")) {
                return 14;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1872765899:
            if (var1.equals("CGLIB$print2")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        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 13;
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 22;
                }
            }
            break;
        case -124978608:
            if (var1.equals("CGLIB$equals")) {
                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 9;
                    }
                }
            }
            break;
        case -29025554:
            if (var1.equals("CGLIB$hashCode")) {
                switch(var2.length) {
                case 0:
                    return 16;
                }
            }
            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 8;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            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 20;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 11;
                    }
                }
            }
            break;
        case 770871766:
            if (var1.equals("CGLIB$print")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
                        return 21;
                    }
                }
            }
            break;
        case 1543336190:
            if (var1.equals("CGLIB$toString")) {
                switch(var2.length) {
                case 0:
                    return 15;
                }
            }
            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 6;
                        }
                        break;
                    case 1364160985:
                        if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
                            return 4;
                        }
                    }
                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 10;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 12;
                    }
                }
            }
            break;
        case 1951977611:
            if (var1.equals("CGLIB$clone")) {
                switch(var2.length) {
                case 0:
                    return 14;
                }
            }
        }

        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 {
        c614e522 var10000 = (c614e522)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.print();
                return null;
            case 8:
                c614e522.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 9:
                c614e522.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 10:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 11:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 12:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 13:
                return var10000.getCallbacks();
            case 14:
                return var10000.CGLIB$clone();
            case 15:
                return var10000.CGLIB$toString();
            case 16:
                return new Integer(var10000.CGLIB$hashCode());
            case 17:
                var10000.CGLIB$print();
                return null;
            case 18:
                return new Boolean(var10000.CGLIB$equals(var3[0]));
            case 19:
                var10000.CGLIB$print2();
                return null;
            case 20:
                c614e522.CGLIB$STATICHOOK1();
                return null;
            case 21:
                return c614e522.CGLIB$findMethodProxy((Signature)var3[0]);
            case 22:
                var10000.print2();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}

MethodProxy.invoke 则对应第二个FastClass类,对应源对象类MyClass,同样getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

[+++]
Spring的CGLIB

demo中在print()方法中调用了print2()方法,输出结果来看,两个方法都被代理了,是因为子类代理对象重写了MyClass的print()和print2()方法,子类方法中都会被interceptor拦截。

但是在spring中,我们知道如上的调用方式print2()是不会被代理拦截的,是为什么呢?

查看了spring源码,cglib最终的调用如图,调用的是methodProxy.invoke且传入的是target对象,执行的是源对象的方法,所以print2()才不会被代理

 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
CGLIB分析_python_内存溢出

CGLIB分析

CGLIB分析,第1张

目录

JDK代理回顾

CGLIB测试代码DEMO

CGLIB 代理class

FastClass

Spring的CGLIB


JDK代理回顾

JDK动态代理的源码

        MyClass myclass = new MyClass();

        // 创建代理对象
        MyInterface o = (MyInterface)Proxy.newProxyInstance(myclass.getClass().getClassLoader(),
                myclass.getClass().getInterfaces(),
                new MyInvocationHandler(myclass));

根据前两个参数,类加载器和接口类, *** 作字节动态创建一个实现了接口类并继承Proxy的$Proxy0.class代理类

public final class $Proxy0 extends Proxy implements MyInterface {
}

此代理类与原对象myclass没有关系,那在调用代理类时如何关联到真正的对象?

Proxy类内部有一个成员变量InvocationHandler h,$Proxy0各个方法内部实际是调用了InvocationHandler来做 *** 作,也就是new 代理对象时传入的第三个参数handler中关联真正的对象,在handler.invoke方法中做增强 *** 作。

    public final void print() throws  {
            super.h.invoke(this, m3, (Object[])null);
    }
CGLIB测试代码DEMO
public class MyClass{
    public void print() {
        System.out.println("主方法啦啦啦啦啦");
        print2();
    }

    public void print2() {
        System.out.println("2222222222222222222");
    }
}


public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("前置 *** 作" + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置 *** 作" + method.getName());
        return result;
    }
}

public class Test {

    public static void main(String[] args) throws Exception {
        // 将产生的代理类class输出到目标文件夹下
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\CglibTest");
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyClass sample = (MyClass) enhancer.create();
        sample.print();
    }
}

执行如下

 这里和JDK代理有区别了,JDK动态代理时原对象方法内部调用另一方法时,是不会被JDK代理从而被拦截到invocationHandler中的。而CGLIB按照输出看起来,对各种姿势的调用都代理了。

CGLIB 代理class

上边代码有一行输出动态产生的class到指定路径,到路径下找到class,粘贴到idea先来看class源码

public class MyClass$$EnhancerByCGLIB$$c614e522 extends MyClass 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;// 设置的MethodInterceptor回调
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$print$0$Method; // 原对象MyClass的print方法
    private static final MethodProxy CGLIB$print$0$Proxy;  //代理对象的print方法
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$print2$1$Method; // 原对象MyClass的print2方法
    private static final MethodProxy CGLIB$print2$1$Proxy;//代理对象的print2方法
    // =================

    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.example.demo.proxy.cglib.MyClass$$EnhancerByCGLIB$$c614e522");
        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$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");

        // 反射获取MyClass的print\print2方法对象Method
        var10000 = ReflectUtils.findMethods(new String[]{"print", "()V", "print2", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.MyClass")).getDeclaredMethods());
        CGLIB$print$0$Method = var10000[0];
        // 针对各方法 创建方法的代理  var1是原对象class, var0则是刚产生的代理对象class
        CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "()V", "print", "CGLIB$print$0");
        CGLIB$print2$1$Method = var10000[1];
        CGLIB$print2$1$Proxy = MethodProxy.create(var1, var0, "()V", "print2", "CGLIB$print2$1");
    }

    final void CGLIB$print$0() {
        super.print();
    }

    public final void print() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print$0$Method, CGLIB$emptyArgs, CGLIB$print$0$Proxy);
        } else {
            super.print();
        }
    }

    final void CGLIB$print2$1() {
        super.print2();
    }

    public final void print2() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$print2$1$Method, CGLIB$emptyArgs, CGLIB$print2$1$Proxy);
        } else {
            super.print2();
        }
    }

    // 。。。。删除了equals\toString等Object的方法和代理

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return CGLIB$print2$1$Proxy;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return CGLIB$print$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    public MyClass$$EnhancerByCGLIB$$c614e522() {
        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) {
        MyClass$$EnhancerByCGLIB$$c614e522 var1 = (MyClass$$EnhancerByCGLIB$$c614e522)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        MyClass$$EnhancerByCGLIB$$c614e522 var10000 = new MyClass$$EnhancerByCGLIB$$c614e522;
        switch(var1.length) {
        case 0:
            var10000.();
            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();
    }
}

创建的三个类

MyClass$$EnhancerByCGLIB$$c614e522.class  MyClass的代理类class,继承自MyClass,继承自MyClass的方法都存在两份,例如print() 和 CGLIB$print$0(),print()中调用MethodInterceptor增强处理,而CGLIB$print$0()则为直接调用MyClass的方法,这也解释了为什么在MyClass中print()调用print2(),两个方法都会被增强,因为代理类对父类的所有方法都重写了,重写后的方法都会走MethodInterceptor。

再看调用代理对象的 *** 作proxy.invokeSuper(obj, args);,proxy是MethodProxy对象,是对方法的代理对象,看源码如下

其中调用了FastClass的invoke方法,而FastClass则是cglib对于jdk反射调用方法效率比较低的优化, 对一个类的方法建立索引,避免了反射调用,来看cglib自动产生的两个FastClass类

FastClass

1、MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367.class

2、MyClass$$FastClassByCGLIB$$7004c485.class

这一组class,是在调用代理方法(MethodProxy.invoke)时动态被创建,在MethodInterceptor中存在两种调用方法MethodProxy.invoke  调用代理对象的对应方法

MethodProxy.invokeSuper 对应第一个FastClass类,对应代理对象类MyClass$$EnhancerByCGLIB$$c614e522,getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

public class MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367 extends FastClass {
    public MyClass$$EnhancerByCGLIB$$c614e522$$FastClassByCGLIB$$ac22b367(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1870561232:
            if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
                return 21;
            }
            break;
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 22;
            }
            break;
        case -1745842178:
            if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1641413109:
            if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 20;
            }
            break;
        case -1411812934:
            if (var10000.equals("CGLIB$hashCode()I")) {
                return 16;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 7;
            }
            break;
        case -1034266769:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case -1025895669:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 8;
            }
            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 -149311009:
            if (var10000.equals("CGLIB$printpublic class MyClass$$FastClassByCGLIB$04c485 extends FastClass {
    public MyClass$$FastClassByCGLIB$04c485(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1798051280:
            if (var10000.equals("print2()V")) {
                return 1;
            }
            break;
        case -1166389848:
            if (var10000.equals("print()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 2;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 3;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 4;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 2;
                    }
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 4;
                }
            }
        }

        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 {
        MyClass var10000 = (MyClass)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.print();
                return null;
            case 1:
                var10000.print2();
                return null;
            case 2:
                return new Boolean(var10000.equals(var3[0]));
            case 3:
                return var10000.toString();
            case 4:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}()V")) {
                return 17;
            }
            break;
        case 56317728:
            if (var10000.equals("CGLIB$print2()V")) {
                return 19;
            }
            break;
        case 374345669:
            if (var10000.equals("CGLIB$equals(Ljava/lang/Object;)Z")) {
                return 18;
            }
            break;
        case 610042816:
            if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case 1132856532:
            if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
                return 13;
            }
            break;
        case 1246779367:
            if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
                return 10;
            }
            break;
        case 1364367423:
            if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
                return 12;
            }
            break;
        case 1517819849:
            if (var10000.equals("CGLIB$toString()Ljava/lang/String;")) {
                return 15;
            }
            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;
            }
            break;
        case 2011844968:
            if (var10000.equals("CGLIB$clone()Ljava/lang/Object;")) {
                return 14;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1872765899:
            if (var1.equals("CGLIB$print2")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        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 13;
                }
            }
            break;
        case -979983579:
            if (var1.equals("print2")) {
                switch(var2.length) {
                case 0:
                    return 22;
                }
            }
            break;
        case -124978608:
            if (var1.equals("CGLIB$equals")) {
                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 9;
                    }
                }
            }
            break;
        case -29025554:
            if (var1.equals("CGLIB$hashCode")) {
                switch(var2.length) {
                case 0:
                    return 16;
                }
            }
            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 8;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 106934957:
            if (var1.equals("print")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            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 20;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 11;
                    }
                }
            }
            break;
        case 770871766:
            if (var1.equals("CGLIB$print")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
                        return 21;
                    }
                }
            }
            break;
        case 1543336190:
            if (var1.equals("CGLIB$toString")) {
                switch(var2.length) {
                case 0:
                    return 15;
                }
            }
            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 6;
                        }
                        break;
                    case 1364160985:
                        if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
                            return 4;
                        }
                    }
                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 10;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 12;
                    }
                }
            }
            break;
        case 1951977611:
            if (var1.equals("CGLIB$clone")) {
                switch(var2.length) {
                case 0:
                    return 14;
                }
            }
        }

        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 {
        c614e522 var10000 = (c614e522)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.print();
                return null;
            case 8:
                c614e522.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 9:
                c614e522.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 10:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 11:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 12:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 13:
                return var10000.getCallbacks();
            case 14:
                return var10000.CGLIB$clone();
            case 15:
                return var10000.CGLIB$toString();
            case 16:
                return new Integer(var10000.CGLIB$hashCode());
            case 17:
                var10000.CGLIB$print();
                return null;
            case 18:
                return new Boolean(var10000.CGLIB$equals(var3[0]));
            case 19:
                var10000.CGLIB$print2();
                return null;
            case 20:
                c614e522.CGLIB$STATICHOOK1();
                return null;
            case 21:
                return c614e522.CGLIB$findMethodProxy((Signature)var3[0]);
            case 22:
                var10000.print2();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
}

MethodProxy.invoke 则对应第二个FastClass类,对应源对象类MyClass,同样getIndex方法根据方法签名或方法名来获取对应方法的索引,然后invoke中根据索引来调用对应方法

 
Spring的CGLIB 

demo中在print()方法中调用了print2()方法,输出结果来看,两个方法都被代理了,是因为子类代理对象重写了MyClass的print()和print2()方法,子类方法中都会被interceptor拦截。

但是在spring中,我们知道如上的调用方式print2()是不会被代理拦截的,是为什么呢?

查看了spring源码,cglib最终的调用如图,调用的是methodProxy.invoke且传入的是target对象,执行的是源对象的方法,所以print2()才不会被代理

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/736895.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存