代理详解(cglib动态代理-源码分析)

上篇文章讲完了jdk的动态代理,基本上对jdk动态代理的原理有了基本认识,比如按class结构填充class文件,通过反射调用方法等。但是jdk有一些问题,比如必须要实现接口,对类的直接代理无法完成,cglib就解决了此类问题,允许直接对类进行代理。

废话不多说先上代码,对类的代理。

被代理类

public class HelloImplClass implements  Hello{
    public void sayHello(String name) {
        System.out.println("hello "+name);
    }
}

增强逻辑,参数的意义后面再说

public class CglibClassProxyIntercepter implements MethodInterceptor {
    
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前...");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("执行后...");
        return object;
    }
}

测试类

public class MainTestClass {
    public static void main(String[] args) throws Exception {
        //代理类class文件存入本地磁盘
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(new CglibClassProxyIntercepter());
        enhancer.setSuperclass(HelloImplClass.class);
        HelloImplClass proxy= (HelloImplClass)  enhancer.create();
        proxy.sayHello("张三");
    }
}

以上就是cglib的基本用法,可以看到我们没有接口,直接通过setSuperClass设置了实现类,就可以生成代理了proxy.

但是代理类是如何生成的呢,又是如何调用的呢,我们看看源码

我们的入口定在enhancer.create()方法,鉴于咱们队jdk动态代理源码分析的比较细,这里就简单的看看

public Object create() {
        classOnly = false;
        argumentTypes = null;
        return createHelper();
    }

Enhancer的cerate()方法并没有做些什么,委托给createHelper方法,代码如下

private Object createHelper() {
        //验证
        preValidate();
        //生成key
        Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
                ReflectUtils.getNames(interfaces),
                filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
                callbackTypes,
                useFactory,
                interceptDuringConstruction,
                serialVersionUID);
        this.currentKey = key;
        //通过key去构造
        Object result = super.create(key);
        return result;
    }

发现这里面也有key,cglib也和jdk的动态代理一样,运用了缓存功能。并且这个key很特殊,相当于一个联合key,由多个字段组成,比如类的名字,filter等,而且这里的KEY_FACTORY也是有cglib代理生成的,在本地只有接口。我们继续看super.create,其在父类AbstractClassGenerator中

protected Object create(Object key) {
        try {
            ClassLoader loader = getClassLoader();
            //这里和jdk动态代理类似,也用到了缓存,classloader为key
            Map<ClassLoader, ClassLoaderData> cache = CACHE;
            ClassLoaderData data = cache.get(loader);
            if (data == null) {
                synchronized (AbstractClassGenerator.class) {
                    cache = CACHE;
                    data = cache.get(loader);
                    if (data == null) {
                        //没有数据则构建新缓存
                        Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
                        //重点:这里生成了class并存入缓存
                        data = new ClassLoaderData(loader);
                        newCache.put(loader, data);
                        CACHE = newCache;
                    }
                }
            }
            this.key = key;
            //从缓存获取数据
            Object obj = data.get(this, getUseCache());
            //根据返回类型的不同去实例化对象
            if (obj instanceof Class) {
                return firstInstance((Class) obj);
            }
            return nextInstance(obj);
        } catch (RuntimeException e) {
            throw e;
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

其中的cache是这样的,也是弱引用类型,不过与jdk动态代理不同的是其二级缓存是ClassLoadData类型

private static volatile Map<ClassLoader, ClassLoaderData> CACHE = new WeakHashMap<ClassLoader, ClassLoaderData>();

我们继续跟踪new ClassLoaderData(loader)看下是如何生成class对象,代码很简单只是做了class生成然后封装,最后放到generatedClasses中,其中的generatedClasses是二级缓存

public ClassLoaderData(ClassLoader classLoader) {
            if (classLoader == null) {
                throw new IllegalArgumentException("classLoader == null is not yet supported");
            }
            this.classLoader = new WeakReference<ClassLoader>(classLoader);
            Function<AbstractClassGenerator, Object> load =
                    new Function<AbstractClassGenerator, Object>() {
                        public Object apply(AbstractClassGenerator gen) {
                            //生成class对象
                            Class klass = gen.generate(ClassLoaderData.this);
                            return gen.wrapCachedClass(klass);
                        }
                    };
            generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
        }

继续看gen.generate()

protected Class generate(ClassLoaderData data) {
        Class gen;
        Object save = CURRENT.get();
        CURRENT.set(this);
        try {
            ClassLoader classLoader = data.getClassLoader();
            if (classLoader == null) {
                throw new IllegalStateException("ClassLoader is null while trying to define class " +
                        getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
                        "Please file an issue at cglib's issue tracker.");
            }
            synchronized (classLoader) {
              //类的名字
              String name = generateClassName(data.getUniqueNamePredicate());              
              data.reserveName(name);
              this.setClassName(name);
            }
            if (attemptLoad) {
                try {
                    gen = classLoader.loadClass(getClassName());
                    return gen;
                } catch (ClassNotFoundException e) {
                    // ignore
                }
            }
            //根据策略生成不同的字节码
            byte[] b = strategy.generate(this);
            String className = ClassNameReader.getClassName(new ClassReader(b));
            ProtectionDomain protectionDomain = getProtectionDomain();
            //利用反射生成class对象
            synchronized (classLoader) { // just in case
                if (protectionDomain == null) {
                    gen = ReflectUtils.defineClass(className, b, classLoader);
                } else {
                    gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
                }
            }
            return gen;
        } catch (RuntimeException e) {
            throw e;
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        } finally {
            CURRENT.set(save);
        }
    }

上面只要做了三件事

1、生成类的名字规则是:被代理class name + "$$" + class generator name + "ByCGLIB" + "$$" + key的hashcode

2、根据策略生成字节码

3、利用反射根据字节码生成class对象

反射生成对象不用说,这里看下策略生成字节码,是在DefaultGeneratorStrategy默认生成策略类中

public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = getClassVisitor();
        //调用ClassGenerator的generateClass去生成
        transform(cg).generateClass(cw);
        //转为字节数组
        return transform(cw.toByteArray());
    }

上面代码根据不同的ClassGenerator去生成不同的字节码,部分ClassGenerator如下,都是用ASM框架去生成字节码的

对ASM框架如何生成字节码我们不做深究,这里就不在细说。到这里代理是如何生成的答题有了一个认识

cglib 是通过ASM框架生成字节码,采用反射去构造代理对象,同时为了提高效率也用了缓存结构,缓存结构也是弱类型。

接下来分析下cglib生成的class对象,一共三个

//HelloImplClass的代理对象
HelloImplClass$$EnhancerByCGLIB$$a85b2ff3.class
//HelloImplClass对应的FastClass对象
HelloImplClass$$FastClassByCGLIB$$67ea48ad.class
//HelloImplClass的代理对象对应的FastClass对象
HelloImplClass$$EnhancerByCGLIB$$a85b2ff3$$FastClassByCGLIB$$f8e31dfe.class

首先看下HelloImplClass$$EnhancerByCGLIB$$a85b2ff3.class代理对象

public class HelloImplClass$$EnhancerByCGLIB$$a85b2ff3 extends HelloImplClass implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    //方法拦截,我们定义的
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    //被代理对象的方法
    private static final Method CGLIB$sayHello$0$Method;
    //代理的方法
    private static final MethodProxy CGLIB$sayHello$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        //var0为代理对象
        Class var0 = Class.forName("com.example.lrn_manager.proxy.cglib_proxy.HelloImplClass$$EnhancerByCGLIB$$a85b2ff3");
        //var1为被代理对象
        Class var1;
        //被代理方法
        CGLIB$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "(Ljava/lang/String;)V"}, (var1 = Class.forName("com.example.lrn_manager.proxy.cglib_proxy.HelloImplClass")).getDeclaredMethods())[0];
        //代理方法
        CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "sayHello", "CGLIB$sayHello$0");
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    }
    //这个方法在fastClass中调用,此调用是执行真正的逻辑
    final void CGLIB$sayHello$0(String var1) {
        super.sayHello(var1);
    }
    //代理对象调用sayHello
    public final void sayHello(String var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        //如果方法拦截不为空则调用intercept方法
        if (var10000 != null) {
            var10000.intercept(this, CGLIB$sayHello$0$Method, new Object[]{var1}, CGLIB$sayHello$0$Proxy);
        } else {
            super.sayHello(var1);
        }
    }

重点已经标注

1、代理类继承了被代理类,这里和jdk动态代理不一样,动态代理是集成Proxy类实现了我们的接口,而cglib是集成了我们的类重写了父类中的方法

2、MethodProxy.create创建了MethodProxy

3、在重写的方法中sayHello中加入了方法拦截逻辑,我们定义的CglibClassProxyIntercepter就是在此处去执行intercept方法的

intercept的四个参数的意思也明确了,填上开始的坑

intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy)方法四个参数的含义

sub:可以看出传入的是this,this指的是代理对象

method:是被代理对象方法对象CGLIB$sayHello$0$Method

objects:指的是方法入参

methodProxy:是方法的代理对象CGLIB$sayHello$0$Proxy

如我们看到在我们开始的例子,调用proxy.sayHello("张三")时,是调用的代理对象的sayHello方法,在代理对象的sayHello调用了CglibClassProxyIntercepter的intercept方法。

我们看下CglibClassProxyIntercepter的逻辑,执行增强

@Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前...");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("执行后...");
        return object;
    }

这里用到methodProxy.invokeSuper方法,还记得在代理类中我们调用了他的create方法,现在说说MethodProxy类

先从create方法说起

public class MethodProxy {
    private Signature sig1;
    private Signature sig2;
    private CreateInfo createInfo;
    
    private final Object initLock = new Object();
    private volatile FastClassInfo fastClassInfo;
    
    
    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
        MethodProxy proxy = new MethodProxy();
        proxy.sig1 = new Signature(name1, desc);
        proxy.sig2 = new Signature(name2, desc);
        proxy.createInfo = new CreateInfo(c1, c2);
        return proxy;
    }

create的参数在代理类中已经给出,如下,var1即c1是被代理对象,var0即c2使代理对象

MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "sayHello", "CGLIB$sayHello$0")

create按名字生成了两个签名,并且按两个class对象生成了一个createinfo,createInfo代码如下

private static class CreateInfo
    {
        Class c1;//被代理对象
        Class c2;//代理对象
        NamingPolicy namingPolicy;
        GeneratorStrategy strategy;
        boolean attemptLoad;
        
        public CreateInfo(Class c1, Class c2)
        {
            this.c1 = c1;
            this.c2 = c2;
            AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
            if (fromEnhancer != null) {
                namingPolicy = fromEnhancer.getNamingPolicy();
                strategy = fromEnhancer.getStrategy();
                attemptLoad = fromEnhancer.getAttemptLoad();
            }
        }
    }

其实貌似什么也没有做,只是实例化了一些东西,做了些准备

接下来看methodProxy.invokeSuper方法

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            init();
            FastClassInfo fci = fastClassInfo;
            return fci.f2.invoke(fci.i2, obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }

这里主要进行了初始化,调用了FastClassInfo的变量的invoke方法,我们只知道这么多,然后一步一步看

FastClassInfo长这样,两个FastClass变量,两个int类型的变量

private static class FastClassInfo
    {
        FastClass f1;//被代理对象FastClass
        FastClass f2;//代理对象FastClass
        int i1;
        int i2;
    }

init方法

private void init()
    {
       
        if (fastClassInfo == null)
        {
            synchronized (initLock)
            {
                if (fastClassInfo == null)
                {
                    CreateInfo ci = createInfo;

                    FastClassInfo fci = new FastClassInfo();
                    fci.f1 = helper(ci, ci.c1);
                    fci.f2 = helper(ci, ci.c2);
                    fci.i1 = fci.f1.getIndex(sig1);
                    fci.i2 = fci.f2.getIndex(sig2);
                    fastClassInfo = fci;
                    createInfo = null;
                }
            }
        }
    }

helper方法用ASM框架去生成了两个FastClass类,我们目前只讲了一个剩下的两个就是在这里生成的

//HelloImplClass对应的FastClass对象
HelloImplClass$$FastClassByCGLIB$$67ea48ad.class
//HelloImplClass的代理对象对应的FastClass对象
HelloImplClass$$EnhancerByCGLIB$$a85b2ff3$$FastClassByCGLIB$$f8e31dfe.class

并且调用了FastClass的getIndex方法,我们看其中的HelloImplClass$$EnhancerByCGLIB$$a85b2ff3$$FastClassByCGLIB$$f8e31dfe.class

public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -2055565910:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 13;
            }
            break;
        case -1882565338:
            if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
                return 15;
            }
            break;
        case -1721191351:
            if (var10000.equals("CGLIB$sayHello$0(Ljava/lang/String;)V")) {
                return 16;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 20;
            }
            break;
        case -1411842725:
            if (var10000.equals("CGLIB$hashCode$3()I")) {
                return 18;
            }
            break;
        case -894172689:
            if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case -623122092:
            if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
                return 14;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return 3;
            }
            break;
        case -419626537:
            if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 7;
            }
            break;
        case 560567118:
            if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
                return 8;
            }
            break;
        case 771401912:
            if (var10000.equals("sayHello(Ljava/lang/String;)V")) {
                return 9;
            }
            break;
        case 811063227:
            if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 5;
            }
            break;
        case 973717575:
            if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
                return 11;
            }
            break;
        case 1221173700:
            if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case 1230699260:
            if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
                return 10;
            }
            break;
        case 1306468936:
            if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
                return 17;
            }
            break;
        case 1584330438:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 12;
            }
            break;
        case 1800494055:
            if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
                return 19;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 0;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 1;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 2;
            }
        }

        return -1;
    }

    
    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        a85b2ff3 var10000 = (a85b2ff3)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.setCallbacks((Callback[])var3[0]);
                return null;
            case 8:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 9:
                var10000.sayHello((String)var3[0]);
                return null;
            case 10:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 11:
                return var10000.getCallbacks();
            case 12:
                a85b2ff3.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 13:
                a85b2ff3.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 14:
                return a85b2ff3.CGLIB$findMethodProxy((Signature)var3[0]);
            case 15:
                return new Boolean(var10000.CGLIB$equals$1(var3[0]));
            case 16:
                var10000.CGLIB$sayHello$0((String)var3[0]);
                return null;
            case 17:
                return var10000.CGLIB$toString$2();
            case 18:
                return new Integer(var10000.CGLIB$hashCode$3());
            case 19:
                return var10000.CGLIB$clone$4();
            case 20:
                a85b2ff3.CGLIB$STATICHOOK1();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

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

getIndex的作用是根据签名去创建索引,invoke方法是根据索引快速执行方法。

FastClass的作用也就明确了,生成索引,并且快速定位调用方法

init的方法作用就是生成索引

fci.f2.invoke(fci.i2, obj, args) 是调用代理类的FastClass 的invoke 快速索引是i2从上面可以看出i2是16,在执行invoke快速case到16去调用代理类的CGLIB$sayHello$0方法,此方法调用了super.sayHello被代理类的真实逻辑。

至此所有的都分析完了,我们再回顾一下。

1)如何生成代理类:底层是通过ASM框架生成字节码,用反射生成代理类

2)代理类是如何调用的:通过FastClass的getindex生成索引,invoke方法定位索引来实现调用方法的

3)执行顺序:代理类sayHello->CglibClassProxyIntercepter类intercept->methodProxy类invokeSuper->代理类FastClass类的invoke->代理类的CGLIB$sayHello$0方法->被代理类的sayHello方法

cglib也可以对接口进行代理,对接口的代理

接口

public interface Hello {

    void sayHello(String name);
}

实现类

public class HelloImpl  implements  Hello{
    public void sayHello(String name) {
        System.out.println("hello "+name);
    }
}

增强逻辑

public class CglibProxyIntercepter implements MethodInterceptor {

    Object hello;

    CglibProxyIntercepter(Object hello){
         this.hello=hello;
    }

    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前...");
        Object object = methodProxy.invoke(hello, objects);
        System.out.println("执行后...");
        return object;
    }
}

测试类MainTest

public class MainTest {
    public static void main(String[] args) throws Exception {
        //代理类class文件存入本地磁盘
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        Enhancer enhancer = new Enhancer();
        Hello hello=new HelloImpl();
        enhancer.setCallback(new CglibProxyIntercepter(hello));
        enhancer.setInterfaces(new Class[]{Hello.class});
        Hello proxy= (Hello)  enhancer.create();
        proxy.sayHello("张三");
    }
    
}

对接口的代理用的方式是setInterface+methodProxy.invoke,而对类的代理是setSuperClass+methodProxy.invokeSuper

对接口的代理的增强逻辑和jdk动态代理非常类似,都是持有目标类。

看下代理类的反编译代码

public class Hello$$EnhancerByCGLIB$$4e6b0c17 implements Hello, Factory {

           其余和对类的代理都一样。。。。

}

和对类的代理不同这里是实现了接口,而对类的代理是集成了目标类。

再看下FastClass反编译代码,发现getIndex的swith case 项少了很多,只有需要实现的方法存在,其余的都没了

public class Hello$$FastClassByCGLIB$$c892f6cb extends FastClass {
    public Hello$$FastClassByCGLIB$$c892f6cb(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case 771401912:
            if (var10000.equals("sayHello(Ljava/lang/String;)V")) {
                return 0;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -2012993625:
            if (var1.equals("sayHello")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.String")) {
                        return 0;
                    }
                }
            }
        }

        return -1;
    }

    public int getIndex(Class[] var1) {
        int var10001 = var1.length;
        return -1;
    }

    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        Hello var10000 = (Hello)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.sayHello((String)var3[0]);
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

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

1)执行顺序:代理类sayHello->CglibClassProxyIntercepter类intercept->methodProxy类invoke->被代理类的FastClass类的invoke->被代理类的sayHello方法

两种方式有本质上的区别,多注意下,而且两种模式不能混用,在类代理中用invoke方法会出现OOM,主要原因时出现了递归调用

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackson陈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值