前言

此博文写作的目的:

  • (Core) 通过了解 CGlib Enhancer 的整个调用链,了解其对于唯一依赖的 ASM 库的调用方式。
  • 基于 Enhancer 对已有字节码进行增强的进一步理解与掌握。

Enhancer

从这篇不是官方但更胜于官方文档的 CGlib Guide 来看,它首先提到的第一个类就是 Enhancer。 其被用于创建 Java 代理类,相较于 Java 标准库的 Proxy 类,它特别地,能够支持那些没有实现接口的类的代理工作。

Enhancer 简单示例展示

针对现有的 SampleClass 类

public class SampleClass {
    public String test(String input) {
        return "Hello World!";
    }
}

使用 CGlib 的 Enhancer 对 SampleClass 进行增强,下列操作的目的在于将 test(String) 方法的返回值改写成 “Hello cglib!”

@Test
public void testFixedValue() {
    // new 一个 Enhancer 实例
    Enhancer enhancer = new Enhancer();
    // 声明使用的父类是 SampleClass
    enhancer.setSuperclass(SampleClass.class);
    // 设置回调方法 - 回调方法实现为 FixedValue (固定值) .
    enhancer.setCallback(new FixedValue() {
        public Object loadObject() throws Exception {
            return "Hello cglib!";
        }
    });
    // 创建 SampleClass 的代理子类实例
    SampleClass proxy = (SampleClass) enhancer.create();
    Assert.assertEquals("Hello cglib!", proxy.test(null));
}

简单测试上述代码,可以了解到确实,代理类的 test(String) 方法的返回值被改写了。 那么,究竟这种操作是如何实现的?下面👇将进行具体的探究。

调用链跟踪

高度抽象的时序图

Enhancer 调用链 时序图

下列内容将根据时序图进行组织,根据调用编号(1,2,3…)进行展开

Seq 1.

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

public Object create(Class[] argumentTypes, Object[] arguments) {
    classOnly = false;
    if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
        throw new IllegalArgumentException("Arguments must be non-null and of equal length");
    }
    this.argumentTypes = argumentTypes;
    this.arguments = arguments;
    return createHelper();
}

上述两个 create(...) 方法。结合上一节的使用示例,可以看到 create() 对应的无参构造。 存在无参构造,那么有参的构造方法显然也是应该被支持id。create(Class[], Object[]) 正是为了这个目标而存在。通过提供参数类型数组和参数实例数组,可以唯一地定位及调用代理类的特定构造方法。

这个方法比较简单,只是将 Enhancer 作为一个数据内容的持有者,重置了新代理类将使用的构造函数参数内容,之后就直接调用了 createHelper()

Seq 2.

private Object createHelper() {
    // 对预声明的回调方法进行验证,要求 [多个回调就必须存在 CallbackFilter 作为调度器]
    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;
    // 调用父类通过的 create(...) 方法
    Object result = super.create(key);
    return result;
}

Seq 3.

protected Object create(Object key) {
    try {
        // 获取用于 加载 生成类 的 ClassLoader
        ClassLoader loader = getClassLoader();
        // 从缓存中加载 这个 ClassLoader 过去加载的相关数据
        Map<ClassLoader, ClassLoaderData> cache = CACHE;
        ClassLoaderData data = cache.get(loader);
        // 如果在 缓存 中找不到,则初始化构造关于这个 ClassLoader 的数据实例
        if (data == null) {
            // 同步
            synchronized (AbstractClassGenerator.class) {
                // 进入同步块后的 再次确认,避免重复初始化构建
                cache = CACHE;
                data = cache.get(loader);
                if (data == null) {
                    // 构建新的 缓存,拷贝原有的缓存集的内容
                    Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
                    // 初始化 ClassLoaderData ,真正的构造操作
                    data = new ClassLoaderData(loader);
                    // 添加到缓存中
                    newCache.put(loader, data);
                    CACHE = newCache;
                }
            }
        }
        this.key = key;
        Object obj = data.get(this, getUseCache());
        if (obj instanceof Class) {
            // 初次实例化操作,就是 Class 利用反射来进行实例化
            return firstInstance((Class) obj);
        }
        // 非初次实例化,则是从 ClassLoaderData 中得到的之前维护的内容
        return nextInstance(obj);
    } catch (RuntimeException e) {
        throw e;
    } catch (Error e) {
        throw e;
    } catch (Exception e) {
        throw new CodeGenerationException(e);
    }
}

这部分内容比较多,且是调用链比较重要的一环。Seq 4.Seq 5. 将作为其子内容进行调用,但为了本博文的结构完整, Seq 4. & Seq5. 的标题与 Seq 3. 标题同级

Seq 4.

首先应该认识到,每个被加载的 Class ,在 equal 的判断过程中,依据的是同一个 ClassLoader 加载的同一 Class 才被认为是相同的,否则即使 Class 是同一个,但仍会被认为是不同的(由不同的 ClassLoader 加载)。

public ClassLoader getClassLoader() {
    ClassLoader t = classLoader;
    if (t == null) {
        t = getDefaultClassLoader();
    }
    if (t == null) {
        t = getClass().getClassLoader();
    }
    if (t == null) {
        t = Thread.currentThread().getContextClassLoader();
    }
    if (t == null) {
        throw new IllegalStateException("Cannot determine classloader");
    }
    return t;
}

因此,在这部分中,首先需要确定的是由哪个 ClassLoader 进行加载的工作。getClassLoader() 的确定顺序是:

  1. 具体实现类声明的 默认 ClassLoader 为第一优先级
  2. 加载当前类(这里是 Enhancer) 的 ClassLoader 为第二优先级
  3. 当前线程上下文 ClassLoader 为第三优先级
  4. 抛出异常

回到 Seq 3. 的内容, 下一步是对当前这个AbstractClassGenerator 维护的 CACHE 进行处理,如果在 CACHE 中能够得到以确定的 ClassLoader 为 Key 的键值对,则直接获取 ClassLoader 对应的值,否则将进行初始化构建一个新的 ClassLoaderData 作为这个 ClassLoader 的值。

Seq 5.

在构建 ClassLoaderData 的过程中,最重要的一步:

public ClassLoaderData(ClassLoader classLoader) {
    // ClassLoader 不可为空
    if (classLoader == null) {
        throw new IllegalArgumentException("classLoader == null is not yet supported");
    }
    // 构建 ClassLoader 的弱引用
    this.classLoader = new WeakReference<ClassLoader>(classLoader);
    // 写了个后置调用的函数,用于懒加载,只有调用了 load.apply(...) 才会构建 生成类
    Function<AbstractClassGenerator, Object> load =
            new Function<AbstractClassGenerator, Object>() {
                public Object apply(AbstractClassGenerator gen) {
                    Class klass = gen.generate(ClassLoaderData.this);
                    return gen.wrapCachedClass(klass);
                }
            };
    generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}

构建了一个 Function 实例,这个 Function 作为函数式接口,预定义执行的具体流程,但由上下文确定具体的调用时刻。

Seq 6.

在正确得到了 ClassLoader 对应的 ClassLoaderData 之后,ClassLoaderData 的 get(...) 方法将在特定的 ClassLoader 之下,进行更具体的加载新生成类的工作。 当然,这里的前提是新的生成类的字节码已经被构建:)

public Object get(AbstractClassGenerator gen, boolean useCache) {
    // 标记为不使用缓存,直接构建 新的生成类
    if (!useCache) {
      return gen.generate(ClassLoaderData.this);
    }
    // 使用缓冲的情况
    else {
      Object cachedValue = generatedClasses.get(gen);
      return gen.unwrapCachedValue(cachedValue);
    }
}

可以看到 gen.generate(ClassLoaderData.this) 这段代码在 get(...) 方法和上一小节 ClassLoaderData(...) 构造方法的 Function 函数式实例都出现了。

实际上,这也是触发 ClassLoader 来加载动态生成的新 Class 的唯一入口。

判断逻辑else 内容的唯一区别就在于其构建的是一个加载缓存,将真正触发 gen.generate(ClassLoaderData.this) 的逻辑延迟。(不过,最终也还是会进行调用的,:) 这是毋庸置疑的)。

Seq 7.

protected Class generate(ClassLoaderData data) {
    Class gen;
    Object save = CURRENT.get();
    CURRENT.set(this);
    try {
        // 拿到用于加载生成类的 ClassLoader
        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 {
                // 尝试直接通过 ClassLoader 进行加载
                gen = classLoader.loadClass(getClassName());
                return gen;
            } catch (ClassNotFoundException e) {
                // ignore
            }
        }
        // 策略下的生成类构建方法
        byte[] b = strategy.generate(this);
        // 通过解析字节码的形式获取 生成类的 className
        String className = ClassNameReader.getClassName(new ClassReader(b));
        ProtectionDomain protectionDomain = getProtectionDomain();
        synchronized (classLoader) { // just in case
            // 反射的形式加载 Class 类
            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);
    }
}

这个方法,就是操作字节码,加载 Class 的核心调度方法。

可以看到 generateClassName(...) 方法将构建一个当前 ClassLoader 下唯一, 不重复的新的类名。

strategy.generate(this) 将通过特定策略实现的形式生成新的字节码

ReflectUtils.defineClass(className, b, classLoader) 将使用反射使得 ClassLoader 来加载这个新的生成类。

Seq 8.

生成新的不重复类名这部分不做过多陈述,可以简单进行了解,并熟悉 CGlib 默认的新类名的命名规则

// DefaultNamePolicy
public String getClassName(String prefix, String source, Object key, Predicate names) {
    if (prefix == null) {
        prefix = "net.sf.cglib.empty.Object";
    } else if (prefix.startsWith("java")) {
        prefix = "$" + prefix;
    }
    String base =
        prefix + "$$" +
        source.substring(source.lastIndexOf('.') + 1) +
        getTag() + "$$" +
        Integer.toHexString(STRESS_HASH_CODE ? 0 : key.hashCode());
    String attempt = base;
    int index = 2;
    while (names.evaluate(attempt))
        attempt = base + "_" + index++;
    return attempt;
}

Seq 9.

// 下列是 DefaultGeneratorStrategy 的实现
public byte[] generate(ClassGenerator cg) throws Exception {
    DebuggingClassWriter cw = getClassVisitor();
    transform(cg).generateClass(cw);
    return transform(cw.toByteArray());
}

Seq 10.

调用 generateClass(ClassVisitor) 将获得到新类的字节码。

public void generateClass(ClassVisitor v) throws Exception {
    // 确定生成类的 父类
    Class sc = (superclass == null) ? Object.class : superclass;

    // 父类标识符不可以为 final
    if (TypeUtils.isFinal(sc.getModifiers()))
        throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
    // 获取父类直接声明的构造方法
    List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
    filterConstructors(sc, constructors);

    // Order is very important: must add superclass, then
    // its superclass chain, then each interface and
    // its superinterfaces.
    List actualMethods = new ArrayList();
    List interfaceMethods = new ArrayList();
    final Set forcePublic = new HashSet();
    // 从父类中提取各种信息
    getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);

    List methods = CollectionUtils.transform(actualMethods, new Transformer() {
        public Object transform(Object value) {
            Method method = (Method)value;
            int modifiers = Constants.ACC_FINAL
                | (method.getModifiers()
                   & ~Constants.ACC_ABSTRACT
                   & ~Constants.ACC_NATIVE
                   & ~Constants.ACC_SYNCHRONIZED);
            if (forcePublic.contains(MethodWrapper.create(method))) {
                modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
            }
            return ReflectUtils.getMethodInfo(method, modifiers);
        }
    });

    ClassEmitter e = new ClassEmitter(v);
    if (currentData == null) {
    e.begin_class(Constants.V1_2,
                  Constants.ACC_PUBLIC,
                  getClassName(),
                  Type.getType(sc),
                  (useFactory ?
                   TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
                   TypeUtils.getTypes(interfaces)),
                  Constants.SOURCE_FILE);
    } else {
        e.begin_class(Constants.V1_2,
                Constants.ACC_PUBLIC,
                getClassName(),
                null,
                new Type[]{FACTORY},
                Constants.SOURCE_FILE);
    }
    List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());

    e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
    e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
    if (!interceptDuringConstruction) {
        e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
    }
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
    if (serialVersionUID != null) {
        e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
    }

    for (int i = 0; i < callbackTypes.length; i++) {
        e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
    }
    // This is declared private to avoid "public field" pollution
    e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);

    if (currentData == null) {
        emitMethods(e, methods, actualMethods);
        emitConstructors(e, constructorInfo);
    } else {
        emitDefaultConstructor(e);
    }
    emitSetThreadCallbacks(e);
    emitSetStaticCallbacks(e);
    emitBindCallbacks(e);

    if (useFactory || currentData != null) {
        int[] keys = getCallbackKeys();
        emitNewInstanceCallbacks(e);
        emitNewInstanceCallback(e);
        emitNewInstanceMultiarg(e, constructorInfo);
        emitGetCallback(e, keys);
        emitSetCallback(e, keys);
        emitGetCallbacks(e);
        emitSetCallbacks(e);
    }

    e.end_class();
}

generateClass(...) 执行的操作和 ASM 库的 ClassVisitor 访问 Class 文件结构的流程基本类似。

从上述截取到的部分代码,例如:

e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), Type.getType(sc), 
        (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)),
        Constants.SOURCE_FILE);
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);

都与 classVisitor.visit(...) 以及 classVisitor.visitField(...) 相当类似。而事实上,这些方法的具体实现也确实调用了 cv.visitXxx(…) 。 毕竟,作为 CGlib 唯一依赖的库,ASM 还是可以说是难以替代的(既然已经有了可用的轮子,又何必重复造呢?)

构造的实例

下面将展示通过 CGlib 生成的新的类(由于生成的是字节码,懒得再自行解析 ClassFile 的内容,所有直接用 IDEA 做了字节码的解析)

首先展示的需要进行增强的 SampleClass 的具体内容

public class SampleClass {
    public String test(String input) {
        return "Hello World!";
    }
}

用于增强的简单代码

// 省略部分代码
public static void main(String... args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(SampleClass.class);
    enhancer.setCallback(new FixedValue() {
        public Object loadObject() throws Exception {
            return "Hello cglib!";
        }
    });
    SampleClass proxy = (SampleClass) enhancer.create();
}

动态生成的新的类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

// 不用过多关注,只是 CGlib 保证生成类与原有的类一定属于同一包下,偷懒直接把 SampleClass 写在 CGlib 项目里了
package net.sf.cglib.samples;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.FixedValue;

/**
 * 新的类名,通过 $$EnhancerByCGLIB 以及 $$7cd64b81(这个是哈希值) 对类名进行唯一区分 
 * 如果还是重复了,在动态生成前会进行类名的检测,并通过增加序号 "_<index>" 的形式进行进一步区分
 *
 * 可以看到新生成的类继承了 SampleClass 
 */
public class SampleClass$$EnhancerByCGLIB$$7cd64b81 extends SampleClass 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;

    // 绑定一个在增强中声明的 Callback 实例
    private FixedValue CGLIB$CALLBACK_0;
    // 绑定一个静态的回调调度实例
    private static Object CGLIB$CALLBACK_FILTER;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
    }

    /**
      * 对 test(String) 的方法的增强
      */ 
    public final String test(String var1) {
        // 在方法块中拿到 Callback 实例
        FixedValue var10000 = this.CGLIB$CALLBACK_0;
        // 为空则尝试获取
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        // 触发回调实例的方法获得返回值
        return (String)var10000.loadObject();
    }

    /**
      * 由于此次增强只声明了一个 Callback
      * 因此所有方法的增强都相同, 都是调用这个回调方法获取
      */
    public final boolean equals(Object var1) {
        FixedValue var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        Object var2 = var10000.loadObject();
        /**
         * 但是,此处会尝试强制转型
         * 同时在最终执行失败的时候直接抛出运行时异常
         * 毕竟上面增强的时候返回固定值 "Hello, cglib!"
         */
        return var2 == null ? false : (Boolean)var2;
    }

    public final String toString() {
        FixedValue var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return (String)var10000.loadObject();
    }

    public final int hashCode() {
        FixedValue var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        Object var1 = var10000.loadObject();
        return var1 == null ? 0 : ((Number)var1).intValue();
    }

    protected final Object clone() throws CloneNotSupportedException {
        FixedValue var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000.loadObject();
    }

    public SampleClass$$EnhancerByCGLIB$$7cd64b81() {
        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) {
        SampleClass$$EnhancerByCGLIB$$7cd64b81 var1 = (SampleClass$$EnhancerByCGLIB$$7cd64b81)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 = (FixedValue)((Callback[])var10000)[0];
        }

    }

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

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

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        SampleClass$$EnhancerByCGLIB$$7cd64b81 var10000 = new SampleClass$$EnhancerByCGLIB$$7cd64b81;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        FixedValue 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 = (FixedValue)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 = (FixedValue)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

从上面的生成类可以看出来,CGlib 所进行的增强,是在不直接对原有的方法体内容进行改造的基础上(例如上面的 test(String) 方法,没有直接改写成 return "Hello, cglib! 的形式),对方法执行之前入参或者方法执行之后的返回值进行一定的处理。

主要使用的形式就是将回调实例与原有方法进行绑定,并通过调用回调方法来实现方法的增强。

  __                    __                  
 / _| __ _ _ __   __ _ / _| ___ _ __   __ _ 
| |_ / _` | '_ \ / _` | |_ / _ \ '_ \ / _` |
|  _| (_| | | | | (_| |  _|  __/ | | | (_| |
|_|  \__,_|_| |_|\__, |_|  \___|_| |_|\__, |
                 |___/                |___/