CGLIB动态代理源码分析


cglib动态代理通过实现子类的方式对目标类进行增强。

简单案例

1. 首先建一个目标类Dao

public class Dao {
    
    public void update(String name) {
        System.out.println("Dao.update()");
    }
    
    public void select() {
        System.out.println("Dao.select()");
    }
}

2. 实现一个方法拦截器DaoProxy

/**
 * cglib实现动态代理,对被代理对象方法进行拦截
 *
 */
public class DaoProxy implements MethodInterceptor {

    /**
     * Object:cglib生成的代理对象
     * Method:被代理对象的方法
     * Object[]:方法参数
     * MethodProxy:代理对象的方法
     */

    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
        System.out.println("Before Method Invoke");
        proxy.invokeSuper(object, objects);
        System.out.println("After Method Invoke");

        return object;
    }
}

3. 创建代理对象

public class CglibTest {
        public static void main(String[] args) {

               // 生成的代理类文件存入本地磁盘
               System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\IdeaProjects\\demo\\com\\cglib");

               // 通过CGLIB动态代理获取代理对象的过程
               Enhancer enhancer = new Enhancer();
               // 设置enhancer对象的父类
               enhancer.setSuperclass(Dao.class);
               // 设置enhancer的回调对象
               enhancer.setCallback(new DaoProxy());

               // 创建代理对象
               Dao dao = (Dao)enhancer.create();
               // // 通过代理对象调用目标方法
               dao.update("yukang");
               dao.select();
        }
}

4. 输出结果

Before Method Invoke
Dao.update()
After Method Invoke
Before Method Invoke
Dao.select()
After Method Invoke

源码分析

大概流程

1. 设置父类(目标类)、设置回调对象(方法拦截器),并生成代理类的字节码文件
2. 使用ClassLoader将字节码文件加载到JVM
3. 创建代理类实例对象,执行对象的目标方法

cglib动态代理涉及到的主要类

  • net.sf.cglib.proxy.MethodInterceptor
  • net.sf.cglib.proxy.Enhancer
  • net.sf.cglib.core.AbstractClassGenerator
  • net.sf.cglib.core.DebuggingClassWriter

MethodInterceptor.java

自定义的方法拦截器要实现该接口,重写intercept方法

public class DaoProxy implements MethodInterceptor {
    /**
     * Object:cglib生成的代理对象
     * Method:被代理对象方法
     * Object[]:方法入参
     * MethodProxy:代理的方法
     */

    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
        System.out.println("Before Method Invoke");
        proxy.invokeSuper(object, objects);
        System.out.println("After Method Invoke");
        return object;
    }
}

Enhancer.java

// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
 // 设置enhancer对象的父类
 enhancer.setSuperclass(Dao.class);
 // 设置enhancer的回调对象
 enhancer.setCallback(new DaoProxy());

 // 创建代理对象
 Dao dao = (Dao)enhancer.create();

Enhancer有个静态代码块会被先执行,然后执行create()

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

private Object createHelper() {
    // 验证,不重要
    this.validate();
    if (this.superclass != null) {
        this.setNamePrefix(this.superclass.getName());
    } else if (this.interfaces != null) {
        this.setNamePrefix(this.interfaces[ReflectUtils.findPackageProtected(this.interfaces)].getName());
    }
    // Enhancer.EnhancerKey KEY_FACTORY在静态代码块中被初始化,通过CGLIB动态生成的实现类
    // 父类使用EnhancerKey创建对象
    return super.create(KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter, this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID));
}

AbstractClassGenerator.java

protected Object create(Object key) {
        try {
            Class gen = null;
            AbstractClassGenerator.Source var3 = this.source;
            synchronized(this.source) {
                // 获取加载器,就是Enhancer.EnhancerKey的类加载器
                ClassLoader loader = this.getClassLoader();
                Map cache2 = null;
                // 使用WeakHashMap缓存,以classLoader为key
                cache2 = (Map)this.source.cache.get(loader);
                if (cache2 == null) {
                    cache2 = new HashMap();
                    ((Map)cache2).put(NAME_KEY, new HashSet());
                    this.source.cache.put(loader, cache2);
                } else if (this.useCache) {
                    Reference ref = (Reference)((Map)cache2).get(key);
                    gen = (Class)(ref == null ? null : ref.get());
                }
                // 缓存中如果存在该代理类,则直接返回代理类对象
                if (gen == null) {
                    Object save = CURRENT.get();
                    CURRENT.set(this);

                    Object var24;
                    try {
                        this.key = key;
                        // 第一次attemptLoad为false
                        if (this.attemptLoad) {
                            try {
                                // 使用ClassLoader加载到JVM
                                gen = loader.loadClass(this.getClassName());
                            } catch (ClassNotFoundException var17) {
                                ;
                            }
                        }

                        if (gen == null) {
                            // 生成字节,经过这里attemptLoad变为true,会再次执行create(Object key)方法
                            byte[] b = this.strategy.generate(this);
                            // 生成类名称
                            String className = ClassNameReader.getClassName(new ClassReader(b));
                            // 放入缓存
                            this.getClassNameCache(loader).add(className);
                            // 反射生成代理类class
                            gen = ReflectUtils.defineClass(className, b, loader);
                        }

                        if (this.useCache) {
                            ((Map)cache2).put(key, new WeakReference(gen));
                        }
                        // 实例化代理类对象,在Enhance中执行
                        var24 = this.firstInstance(gen);
                    } finally {
                        CURRENT.set(save);
                    }

                    return var24;
                }
            }

            return this.firstInstance(gen);
        } catch (RuntimeException var20) {
            throw var20;
        } catch (Error var21) {
            throw var21;
        } catch (Exception var22) {
            throw new CodeGenerationException(var22);
        }
    }

DebuggingClassWriter.java

生成字节码byte[] b = this.strategy.generate(this);

public byte[] generate(ClassGenerator cg) throws Exception {
    ClassWriter cw = this.getClassWriter();
    this.transform(cg).generateClass(cw);
    return this.transform(cw.toByteArray());
}

其中getClassWriter();

protected ClassWriter getClassWriter() throws Exception {
     return new DebuggingClassWriter(true);
}

DebuggingClassWriter重写了toByteArray()方法,调用父类ClassWritertoByteArray()方法生成字节

public byte[] toByteArray() {
        return (byte[])AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                byte[] b = DebuggingClassWriter.super.toByteArray();
                if (DebuggingClassWriter.debugLocation != null) {
                    String dirs = DebuggingClassWriter.this.className.replace('.', File.separatorChar);

                    try {
                        (new File(DebuggingClassWriter.debugLocation + File.separatorChar + dirs)).getParentFile().mkdirs();
                        File file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".class");
                        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));

                        try {
                            out.write(b);
                        } finally {
                            out.close();
                        }
                        // asm技术生成class文件
                        if (DebuggingClassWriter.traceEnabled) {
                            file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".asm");
                            out = new BufferedOutputStream(new FileOutputStream(file));

                            try {
                                ClassReader cr = new ClassReader(b);
                                PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
                                TraceClassVisitor tcv = new TraceClassVisitor((ClassVisitor)null, pw);
                                cr.accept(tcv, false);
                                pw.flush();
                            } finally {
                                out.close();
                            }
                        }
                    } catch (IOException var17) {
                        throw new CodeGenerationException(var17);
                    }
                }

                return b;
            }
        });
    }

首先看DebuggingClassWriter.debugLocation,默认null,可以设置路径,只有不为null时才会在本地生成class文件

private static String debugLocation = System.getProperty("cglib.debugLocation");

本想打断点看一下AccessController.doPrivileged的执行流程,结果debugger直接跳过了,后来发现这个方法是native

public static native <T> T doPrivileged(PrivilegedAction<T> action);

asm框架生成class文件

首先 DebuggingClassWriter有个静态代码块,除了打印日志显示代理类class文件生成目录外,还判断cglib包下的是否存在TraceClassVisitor类(注意jdk下有一个一样的类),存在的的话赋值traceEnabled = true,然后会用asm技术去生成class文件

static {
    if (debugLocation != null) {
        System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");

        try {
            Class.forName("net.sf.cglib.asm.util.TraceClassVisitor");
            traceEnabled = true;
        } catch (Throwable var1) {
            ;
        }
    }
}

回到Enhancer实例化代理类对象

直接看this.firstInstance(gen);怎么实例化

protected Object firstInstance(Class type) throws Exception {
   return this.classOnly ? type : this.createUsingReflection(type);
}

private Object createUsingReflection(Class type) {
    setThreadCallbacks(type, this.callbacks);

    Object var2;
    try {
        if (this.argumentTypes == null) {
        	// 参数类型为空的实例化方法,这里指的是代理类的构造方法参数
            var2 = ReflectUtils.newInstance(type);
            return var2;
        }
        // 参数不为空的实例化方法
        var2 = ReflectUtils.newInstance(type, this.argumentTypes, this.arguments);
    } finally {
        setThreadCallbacks(type, (Callback[])null);
    }

    return var2;
}

我们创建代理类对象时有两种方法
create()就表示代理类用默认的构造函数实例化对象
create(Class[] argumentTypes, Object[] arguments)就表示代理类用有参的构造函数实例化对象
在这里插入图片描述
最后会调用ReflectUtils.newInstance(Constructor cstruct, Object[] args)实例化代理类对象

public static Object newInstance(Constructor cstruct, Object[] args) {
    boolean flag = cstruct.isAccessible();

    Object var4;
    try {
        cstruct.setAccessible(true);
        Object result = cstruct.newInstance(args);
        var4 = result;
    } catch (InstantiationException var10) {
        throw new CodeGenerationException(var10);
    } catch (IllegalAccessException var11) {
        throw new CodeGenerationException(var11);
    } catch (InvocationTargetException var12) {
        throw new CodeGenerationException(var12.getTargetException());
    } finally {
        cstruct.setAccessible(flag);
    }

    return var4;
}

生成的代理类

生成了好多代理类,具体看目标类的代理类
在这里插入图片描述
代理类中Method为被代理对象方法,MethodProxy为代理的方法,可以看到是一 一对应的

private static final Method CGLIB$update$0$Method;
private static final MethodProxy CGLIB$update$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$select$1$Method;
private static final MethodProxy CGLIB$select$1$Proxy;
private static final Method CGLIB$finalize$2$Method;
private static final MethodProxy CGLIB$finalize$2$Proxy;
private static final Method CGLIB$equals$3$Method;
private static final MethodProxy CGLIB$equals$3$Proxy;
private static final Method CGLIB$toString$4$Method;
private static final MethodProxy CGLIB$toString$4$Proxy;
private static final Method CGLIB$hashCode$5$Method;
private static final MethodProxy CGLIB$hashCode$5$Proxy;
private static final Method CGLIB$clone$6$Method;
private static final MethodProxy CGLIB$clone$6$Proxy;

在静态代码块中被初始化

static void CGLIB$STATICHOOK1() {
    CGLIB$THREAD_CALLBACKS = new ThreadLocal();
    Class var0;
    ClassLoader var10000 = (var0 = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao$$EnhancerByCGLIB$$f018efe")).getClassLoader();
    CGLIB$emptyArgs = new Object[0];
    CGLIB$update$0$Proxy = MethodProxy.create(var10000, (CGLIB$update$0$Method = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao").getDeclaredMethod("update", Class.forName("java.lang.String"))).getDeclaringClass(), var0, "(Ljava/lang/String;)V", "update", "CGLIB$update$0");
    CGLIB$select$1$Proxy = MethodProxy.create(var10000, (CGLIB$select$1$Method = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao").getDeclaredMethod("select")).getDeclaringClass(), var0, "()V", "select", "CGLIB$select$1");
    CGLIB$finalize$2$Proxy = MethodProxy.create(var10000, (CGLIB$finalize$2$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize")).getDeclaringClass(), var0, "()V", "finalize", "CGLIB$finalize$2");
    CGLIB$equals$3$Proxy = MethodProxy.create(var10000, (CGLIB$equals$3$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals", Class.forName("java.lang.Object"))).getDeclaringClass(), var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3");
    CGLIB$toString$4$Proxy = MethodProxy.create(var10000, (CGLIB$toString$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString")).getDeclaringClass(), var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$4");
    CGLIB$hashCode$5$Proxy = MethodProxy.create(var10000, (CGLIB$hashCode$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode")).getDeclaringClass(), var0, "()I", "hashCode", "CGLIB$hashCode$5");
    CGLIB$clone$6$Proxy = MethodProxy.create(var10000, (CGLIB$clone$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone")).getDeclaringClass(), var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$6");
}

代理类的执行流程

// 创建代理对象
Dao dao = (Dao)enhancer.create();
// // 通过代理对象调用目标方法
dao.update("yukang");

代理类执行update方法时

public final void update(String var1) {
    // 这里获取的就是自定义方法拦截器DaoProxy,一开始就初始化的
    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$update$0$Method, new Object[]{var1}, CGLIB$update$0$Proxy);
    } else {
        super.update(var1);
    }
}

var10000.intercept(this, CGLIB$update$0$Method, new Object[]{var1}, CGLIB$update$0$Proxy);,执行的是自定义方法拦截器DaoProxy**.intercept**

/**
     * Object:cglib生成的代理对象
     * Method:被代理对象方法
     * Object[]:方法入参
     * MethodProxy:代理的方法
     */
    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
        System.out.println("Before Method Invoke");
        proxy.invokeSuper(object, objects);
        System.out.println("After Method Invoke");

        return object;
    }

proxy.invokeSuper(object, objects);执行的是MethodProxy**.invokeSuper**

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        //  f2代理类FastClass
        return this.f2.invoke(this.i2, obj, args);
    } catch (InvocationTargetException var4) {
        throw var4.getTargetException();
    }
}

这里的f2通过代理对象生成的,是在静态代码块中执行MethodProxy**.create传递进来的**

// c1被代理对象,c2代理对象
public static MethodProxy create(ClassLoader loader, Class c1, Class c2, String desc, String name1, String name2) {
    final Signature sig1 = new Signature(name1, desc);
    Signature sig2 = new Signature(name2, desc);
    FastClass f1 = helper(loader, c1);// 被代理类FastClass
    FastClass f2 = helper(loader, c2);// 代理类FastClass
    int i1 = f1.getIndex(sig1);// 被代理类的方法签名(index)
    int i2 = f2.getIndex(sig2);// 代理类的方法签名(index)
    MethodProxy proxy;
    if (i1 < 0) {
        proxy = new MethodProxy() {
            public Object invoke(Object obj, Object[] args) throws Throwable {
                throw new IllegalArgumentException("Protected method: " + sig1);
            }
        };
    } else {
        proxy = new MethodProxy();
    }

    proxy.f1 = f1;
    proxy.f2 = f2;
    proxy.i1 = i1;
    proxy.i2 = i2;
    proxy.sig = sig1;
    proxy.superName = name2;
    return proxy;
}

this.f2.invoke(this.i2, obj, args);,执行的就是代理类的FastClass**.invok**
在这里插入图片描述
根据方法签名(index)快速找到代理类的方法

public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    f018efe var10000 = (f018efe)var2;
    int var10001 = var1;
    try {
        switch(var10001) {
        case 0:
            return new Boolean(var10000.equals(var3[0]));
       .
       .
       .
        case 16:
            var10000.CGLIB$update$0((String)var3[0]);
            return null;
        .
        .
        .
        }
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }

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

执行代理类的CGLIB$update$0方法,最后执行父类(被代理类)的方法

final void CGLIB$update$0(String var1) {
    super.update(var1);
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值