Java
语言基础

动态代理原理详解(2) - CGLIB实现

简介:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

1. CGLIB简介

在前面动态代理原理详解(一)——JDK实现一文中介绍了JDK默认实现的动态代理功能,JDK动态代理简单易用,底层实现也非常清晰明了,但它只能对接口进行代理,无法为未实现接口的普通类进行代理,这是它最大的缺陷。在这篇文章中将讲解另一个动态代理库——CGLIB。

CGLIB(Code Generator Library)是一个高性能的代码生成库,被广泛应用于AOP框架(Hibernate、Spring、Dynaop)中以提供方法拦截功能,主要以继承目标类的方式来进行拦截实现,因此CGLIB可以对无接口的类进行代理,但这也是CGLIB存在短板的原因所在,它无法代理final修饰的类或方法,因为final类无法被继承,同时final方法无法被重写。

CGLIB代理主要通过操作字节码的方式为对象引入方法调用时访问操作,底层使用了ASM来操作字节码生成新的类,ASM是一个短小精悍的字节码操作框架。CGLIB的应用栈如下:

1.CGLIB技术栈.png

2. CGLIB的简单使用

下面先演示使用如何CGLIB实现与动态代理原理详解(一)——JDK实现一文中讲到的例子相同的代理功能。

在使用JDK动态代理完成的例子中,Bugatti和Ferrari两个类继承自Car接口,JDK依托该接口完成动态代理功能。而CGLIB可以为未实现接口的类进行代理操作,因此这里将这两个类的接口实现过程去掉:

  • Bugatti类的代码如下:
  • package com.coderap.proxy.cglib;
  • import java.util.Random;
  • public class Bugatti {
  • private String info;
  • public Bugatti(String info) {
  • this.info = info;
  • }
  • public void run() {
  • System.out.println(this.info + " car running");
  • try {
  • Thread.sleep(new Random().nextInt(3000));
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • }
  • public String getInfo() {
  • return this.info;
  • }
  • }
  • Ferrari类的代码如下:
  • package com.coderap.proxy.cglib;
  • import java.util.Random;
  • public class Ferrari {
  • private String info;
  • public Ferrari(String info) {
  • this.info = info;
  • }
  • public void run() {
  • System.out.println(this.info + " car running");
  • try {
  • Thread.sleep(new Random().nextInt(3000));
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • }
  • public String getInfo() {
  • return this.info;
  • }
  • }

然后通过实现net.sf.cglib.proxy.MethodInterceptor接口,构建方法拦截类SpeedTestMethodInterceptor;该类类似于JDK动态代理中实现了InvocationHandler接口的SpeedTestInvocationHandler类:

  • package com.coderap.proxy.cglib;
  • import net.sf.cglib.proxy.MethodInterceptor;
  • import net.sf.cglib.proxy.MethodProxy;
  • import java.lang.reflect.Method;
  • public class SpeedTestMethodInterceptor implements MethodInterceptor {
  • @Override
  • public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  • if (object != null) {
  • if ("run".equals(method.getName())) {
  • // 获取车型号
  • String carInfo = "";
  • if (object instanceof Bugatti) {
  • carInfo = ((Bugatti)object).getInfo();
  • } else if (object instanceof Ferrari) {
  • carInfo = ((Ferrari)object).getInfo();
  • }
  • // 开始测速
  • System.out.println("动态测速代理开始执行:" + carInfo + " " + method.getName());
  • SpeedTestUtil.start();
  • // 主要的执行方法
  • Object result = methodProxy.invokeSuper(object, objects);
  • SpeedTestUtil.finish(carInfo, method.getName());
  • return result;
  • } else {
  • return methodProxy.invokeSuper(object, objects);
  • }
  • } else {
  • throw new Throwable("Target Error, You need provide a Car to test");
  • }
  • }
  • }

其中SpeedTestUtil类的代码与之前一样,是用于测试的辅助类:

  • package com.coderap.proxy.cglib;
  • public class SpeedTestUtil {
  • // 存储启动时间
  • private static ThreadLocal<Long> startTime = new ThreadLocal<Long>();
  • public static void start() {
  • // 记录启动时间
  • startTime.set(System.currentTimeMillis());
  • }
  • public static void finish(String carName, String methodName) {
  • // 获取结束时间
  • long finishTime = System.currentTimeMillis();
  • // 打印时间信息
  • System.out.println(carName + " 执行" + methodName + ",耗时:" + (finishTime - startTime.get()) + " ms.\n");
  • }
  • }

有了上面的准备,就可以进行代理过程的测试了,测试代码如下:

  • package com.coderap.proxy.cglib;
  • import net.sf.cglib.core.DebuggingClassWriter;
  • import net.sf.cglib.proxy.Enhancer;
  • public class SpeedTest {
  • public static void main(String[] args) {
  • // 设置CGLib调试输出目录
  • System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/");
  • // 测试Bugatti
  • Enhancer bugattiEnhancer = new Enhancer();
  • bugattiEnhancer.setSuperclass(Bugatti.class);
  • bugattiEnhancer.setCallback(new SpeedTestMethodInterceptor());
  • Bugatti bugatti = (Bugatti) bugattiEnhancer.create(new Class[]{String.class}, new Object[]{"Bugatti Chiron"});
  • bugatti.run();
  • // 测试Ferrari
  • Enhancer ferrariEnhancer = new Enhancer();
  • ferrariEnhancer.setSuperclass(Ferrari.class);
  • ferrariEnhancer.setCallback(new SpeedTestMethodInterceptor());
  • Ferrari ferrari = (Ferrari) ferrariEnhancer.create(new Class[]{String.class}, new Object[]{"Ferrari California T"});
  • ferrari.run();
  • }
  • }

在测试代码中,我们使用System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/");设置了CGLIB在Debug时的调试目录,这个目录会用于放置CGLIB在实现动态代理的过程中产生的Class字节码文件。运行测试代码,可以得到下面的打印信息:

  • CGLIB debugging enabled, writing to '/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/'
  • 动态测速代理开始执行:Bugatti Chiron run
  • Bugatti Chiron car running
  • Bugatti Chiron 执行run,耗时:797 ms.
  • 动态测速代理开始执行:Ferrari California T run
  • Ferrari California T car running
  • Ferrari California T 执行run,耗时:2347 ms.

可以发现,Bugatti和Ferrari两个类的run()方法在执行过程中打印了附加的信息。

3. Enhancer类分析

Enhancer类用于根据相关配置产生指定目标类的代理对象,与JDK动态代理中的Proxy类类似。Enhancer类继承自net.sf.cglib.core.AbstractClassGenerator类,该类实现了生成代理类所需的大多数辅助业务,而生成代理类字节码的工作是由其实现类完成的,比如此处的Enhancer类,这部分细节在后面会讲解。

在上面的例子代码中,创建Enhancer对象后,会通过其setSuperclass(Class superClass)方法来设置目标类,通过其setCallback(Callback callback)方法来设置拦截器,然后通过其create(Class[] argumentTypes, Object[] arguments)方法生成目标类的代理类,并返回代理类的实例;这里主要关注create(Class[] argumentTypes, Object[] arguments)方法,源码如下:

  • 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;
  • // 调用createHelper()方法进行创建
  • return createHelper();
  • }
  • private Object createHelper() {
  • validate();
  • // 检查superClass和interfaces,并记录前缀,用于生成字节码文件
  • if (superclass != null) {
  • setNamePrefix(superclass.getName());
  • } else if (interfaces != null) {
  • setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
  • }
  • // 创建代理对象
  • return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
  • ReflectUtils.getNames(interfaces),
  • filter,
  • callbackTypes,
  • useFactory,
  • interceptDuringConstruction,
  • serialVersionUID));

createHelper()方法的实现可以得知,最后使用了Enhancer的父类——即AbstractClassGenerator类的的create()方法创建的代理对象。

3.1. KEY_FACTORY的生成

在分析AbstractClassGenerator类之前,我们先观察生成传入create()方法的参数所使用的KEY_FACTORY对象,KEY_FACTORY对象的作用正如其名,它是用于根据指定类、接口群、CallbackFilter、CallBack Types、序列化ID等信息生成一个特有的KEY,这个KEY根据前面讲到的信息自定义了hashCode()equals()方法的实现,用于在后面将要讲到的缓存Map(HashMap结构)中作为键,以实现特定方式的比较功能。KEY_FACTORY对象的定义如下:

  • private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class);

CGLIB为了提高类生成的性能,会对已经生成的代理类做缓存处理,缓存的结构是一个WeakHashMap对象,它的键用于标识生成类的唯一标识,这个标识则是使用KeyFactory来生成的。这里我们对该EnhancerKey对象的生成过程深入源码分析,首先是KeyFactory类中create(Class keyInterface)方法相关的代码:

  • public static KeyFactory create(Class keyInterface) {
  • return create(keyInterface, null);
  • }
  • public static KeyFactory create(Class keyInterface, Customizer customizer) {
  • return create(keyInterface.getClassLoader(), keyInterface, customizer);
  • }
  • public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
  • // KeyFactory生成器
  • Generator gen = new Generator();
  • gen.setInterface(keyInterface);
  • gen.setCustomizer(customizer);
  • gen.setClassLoader(loader);
  • return gen.create();
  • }

Generator是KeyFactory的内部类,用于生成KeyFactory对象的生成器,它是上面提到的net.sf.cglib.core.AbstractClassGenerator类的子类,其create()方法源码如下:

  • public KeyFactory create() {
  • // 设置名称前缀
  • setNamePrefix(keyInterface.getName());
  • // 使用父类方法创建KeyFactory
  • return (KeyFactory)super.create(keyInterface.getName());
  • }

最终会调用到AbstractClassGenerator类create(Object)方法,需要注意的是,此时调用该方法的对象其实是KeyFactory的内部类Generator的实例,也就是说,此时this指向的是一个Generator对象。同时,此时传入该方法的参数是EnhancerKey类的全限定名,也即是net.sf.cglib.proxy.Enhancer.EnhancerKey。

3.2. AbstractClassGenerator类与字节码文件的生成

这里最关键是AbstractClassGenerator类的create(Object)方法,它的作用是处理生成字节码文件前期准备工作,包含了对缓存的处理;在这里涉及到的Generator类是AbstractClassGenerator类的子类,而实际上Enhancer类也是AbstractClassGenerator类的子类;create(Object)方法的源码如下:

  • protected Object create(Object key) {
  • try {
  • Class gen = null;
  • // 同步操作
  • synchronized (source) {
  • ClassLoader loader = getClassLoader();
  • // 缓存
  • Map cache2 = null;
  • cache2 = (Map)source.cache.get(loader);
  • if (cache2 == null) {
  • // 如果缓存为空,就新创建一个HashMap对象
  • cache2 = new HashMap();
  • cache2.put(NAME_KEY, new HashSet());
  • source.cache.put(loader, cache2);
  • } else if (useCache) {
  • /**
  • * 如果缓存不为空,且是使用缓存的,就从缓存中根据传入的参数key获取对应的Class对象
  • * 拿到的是引用WeakReference,调用ref.get()拿到类本身
  • * 并将其赋值给gen
  • */
  • Reference ref = (Reference)cache2.get(key);
  • gen = (Class) (( ref == null ) ? null : ref.get());
  • }
  • // 如果不能从缓存中查找到生成类
  • if (gen == null) {
  • Object save = CURRENT.get();
  • CURRENT.set(this);
  • try {
  • this.key = key;
  • if (attemptLoad) {
  • try {
  • /**
  • * 尝试使用类加载器通过全限定名进行加载
  • * 这里我们需要注意getClassName()方法的实现,该方法最终会根据namePrefix来返回
  • * 而namePrefix在前面Generator的create()方法中设置为EnhancerKey类的全限定名
  • */
  • gen = loader.loadClass(getClassName());
  • } catch (ClassNotFoundException e) {
  • // ignore
  • }
  • }
  • // 如果还是没有加载到
  • if (gen == null) {
  • /**
  • * 就使用strategy进行生成,strategy默认是一个DefaultGeneratorStrategy对象
  • * strategy的generate(ClassGenerator)方法调用了子类里的generateClass(ClassVisitor)方法
  • * 用于生成字节码,这部分代码会在后面讲解
  • * 这里需要记住的是,this此时是Generator实例
  • */
  • byte[] b = strategy.generate(this);
  • String className = ClassNameReader.getClassName(new ClassReader(b));
  • // 将className放入NAME_KEY对应的Set中
  • getClassNameCache(loader).add(className);
  • // 根据返回的字节码生成类
  • gen = ReflectUtils.defineClass(className, b, loader);
  • }
  • // 如果使用缓存,就将刚刚获取的类对象gen进行缓存
  • if (useCache) {
  • cache2.put(key, new WeakReference(gen));
  • }
  • // 调用firstInstance()方法,通过类对象创建实例
  • return firstInstance(gen);
  • } finally {
  • CURRENT.set(save);
  • }
  • }
  • }
  • // 调用firstInstance()方法,通过类对象创建实例
  • return firstInstance(gen);
  • } catch (RuntimeException e) {
  • throw e;
  • } catch (Error e) {
  • throw e;
  • } catch (Exception e) {
  • throw new CodeGenerationException(e);
  • }
  • }

该方法的主要流程是先找到类对象,然后根据类对象生成需要的相应的实例;这里先讲解一下获取类对象的流程细节:

  1. 首先尝试从缓存加载对应的类对象,此处用到的缓存是source.cache,它的源码如下:
  • protected static class Source {
  • String name;
  • Map cache = new WeakHashMap();
  • public Source(String name) {
  • this.name = name;
  • }
  • }

在此处用到的Source实例其实是AbstractClassGenerator的子类Generator创建的,因此Source实例的name字段其实是KeyFactory类的全限定名:

  • // Generator类中的代码
  • private static final Source SOURCE = new Source(KeyFactory.class.getName());
  • public Generator() {
  • super(SOURCE);
  • }
  • // AbstractClassGenerator类中的代码
  • protected AbstractClassGenerator(Source source) {
  • this.source = source;
  • }

source.cache是一个两层嵌套Map,第一层键为ClassLoader对象,第二层键为生成类对应的唯一索引名;source.cache的第一层Map使用了WeakHashMap,WeakHashMap的键为弱引用(WeakReference),如果一个WeakHashMap的键被回收,那么它对应用的值也将被自动的被移除。这也是为什么要使用ClassLoader作为键,当ClassLoader被回收,使用这个ClassLoader加载的类也应该被回收,在这时将这个键值对移除是合理的。在第二层Map中,键NAME_KEY就是一个干净的Object对象,它对应的Set存储了当前缓存的所有生成类的类名,用于检测生成类的类名是否重复。

  1. 如果不能从缓存source.cache中查找到生成类,且指定了attemptLoad为true,则尝试使用ClassLoader对象loader加载。

在当前上下文环境中,loader.loadClass(getClassName())中的loader即是EnhancerKey类的类加载器。这里我们分析一下AbstractClassGenerator类的用于获取全限定类名的getClassName()方法,源码如下:

  • final protected String getClassName() {
  • if (className == null)
  • className = getClassName(getClassLoader());
  • return className;
  • }
  • private String getClassName(final ClassLoader loader) {
  • // 先使用ClassLoader尝试从缓存中获取已生成的类的类名集合
  • final Set nameCache = getClassNameCache(loader);
  • /*
  • * 通过命名策略的getClassName()方法尝试从类名集合中查找存在的类名
  • * 注意,此时namePrefix已被设置为了EnhancerKey类的全限定名,可以翻阅前面的代码
  • * source.name也是EnhancerKey类的全限定名
  • * key即是上面create(Object key)方法传入的参数key,也是EnhancerKey类的全限定名
  • */
  • return namingPolicy.getClassName(namePrefix, source.name, key, new Predicate() {
  • public boolean evaluate(Object arg) {
  • return nameCache.contains(arg);
  • }
  • });
  • }
  • // 从缓存中获取类名集合
  • private Set getClassNameCache(ClassLoader loader) {
  • return (Set)((Map)source.cache.get(loader)).get(NAME_KEY);
  • }

我们主要关注namingPolicy对象的实现,该对象由AbstractClassGenerator初始化,默认是一个DefaultNamingPolicy对象,它的getClassName(String prefix, String source, Object key, Predicate names)的源码实现如下:

  • 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(key.hashCode());
  • String attempt = base;
  • int index = 2;
  • while (names.evaluate(attempt))
  • attempt = base + "_" + index++;
  • return attempt;
  • }
  • /**
  • * Returns a string which is incorporated into every generated class name.
  • * By default returns "ByCGLIB"
  • */
  • protected String getTag() {
  • return "ByCGLIB";
  • }

从源码可知,namingPolicy命名策略的默认规则是:被代理类名 + "$$" + Class Generator Name + "ByCGLIB" + "$$" + key的hashCode。注意,此时传入getClassName(String prefix, String source, Object key, Predicate names)方法的prefix就是namePrefix,即EnhancerKey的全限定名——net.sf.cglib.proxy.Enhancer$EnhancerKey,因此我们可以得到最终的字节码文件命名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$ + key的hashCode,记住这个命名。

  1. 如果尝试使用ClassLoader对象loader加载还是失败,说明CGLIB之前并没有生产相应的类Class文件,因此需要根据生成器策略(GeneratorStrategy)来生成字节码。

在这里使用的默认的DefaultGeneratorStrategy生成器策略,调用了该类的实例的generate(ClassGenerator)方法,源码如下:

  • public byte[] generate(ClassGenerator cg) throws Exception {
  • // 获取生产的类字节码文件输出器
  • ClassWriter cw = getClassWriter();
  • /**
  • * 生产字节码文件并输出
  • * 由于此处cg其实是传入的Generator实例,
  • * 因此这里调用的是Generator的generateClass()方法
  • */
  • transform(cg).generateClass(cw);
  • // 以byte数组的形式返回字节码文件内容
  • return transform(cw.toByteArray());
  • }
  • protected ClassWriter getClassWriter() throws Exception {
  • return new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
  • }
  • protected byte[] transform(byte[] b) throws Exception {
  • return b;
  • }

其中DebuggingClassWriter它通过封装ClassWriter,实现了从定义的类结构到字节码的转换工作,并将字节码内容写入我们前面指定的DebuggingClassWriter.DEBUG_LOCATION_PROPERTY目录中,便于调试。

从源码可知,其实该方法内部调用了子类Generator对象的generateClass()方法,完成了类的构建,该方法源码如下:

  • public void generateClass(ClassVisitor v) {
  • ClassEmitter ce = new ClassEmitter(v);
  • // 对定义key工厂类结构的接口进行判断,判断该接口是否只有newInstance一个方法,newInstance的返回值是否为Object
  • Method newInstance = ReflectUtils.findNewInstance(keyInterface);
  • if (!newInstance.getReturnType().equals(Object.class)) {
  • throw new IllegalArgumentException("newInstance method must return Object");
  • }
  • // 获取newInstance的入参类型,此处使用ASM的Type来定义
  • Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
  • ce.begin_class(Constants.V1_2,
  • Constants.ACC_PUBLIC,
  • getClassName(),
  • KEY_FACTORY,
  • new Type[]{ Type.getType(keyInterface) },
  • Constants.SOURCE_FILE);
  • // 生成默认构造函数
  • EmitUtils.null_constructor(ce);
  • // 生成newInstance工厂方法
  • EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
  • // 生成有参构造方法
  • int seed = 0;
  • CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
  • TypeUtils.parseConstructor(parameterTypes),
  • null);
  • e.load_this();
  • e.super_invoke_constructor();
  • e.load_this();
  • for (int i = 0; i < parameterTypes.length; i++) {
  • seed += parameterTypes[i].hashCode();
  • // 为每一个入参生成一个相同类型的类字段
  • ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
  • getFieldName(i),
  • parameterTypes[i],
  • null);
  • e.dup();
  • e.load_arg(i);
  • e.putfield(getFieldName(i));
  • }
  • e.return_value();
  • e.end_method();
  • // 生成hashCode()方法
  • e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
  • int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)];
  • int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)];
  • e.push(hc);
  • for (int i = 0; i < parameterTypes.length; i++) {
  • e.load_this();
  • e.getfield(getFieldName(i));
  • EmitUtils.hash_code(e, parameterTypes[i], hm, customizer);
  • }
  • e.return_value();
  • e.end_method();
  • // 生成equals()方法,在equals()方法中对每个入参都进行判断
  • e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
  • Label fail = e.make_label();
  • e.load_arg(0);
  • e.instance_of_this();
  • e.if_jump(e.EQ, fail);
  • for (int i = 0; i < parameterTypes.length; i++) {
  • e.load_this();
  • e.getfield(getFieldName(i));
  • e.load_arg(0);
  • e.checkcast_this();
  • e.getfield(getFieldName(i));
  • EmitUtils.not_equals(e, parameterTypes[i], fail, customizer);
  • }
  • e.push(1);
  • e.return_value();
  • e.mark(fail);
  • e.push(0);
  • e.return_value();
  • e.end_method();
  • // 生成toString()方法
  • e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
  • e.new_instance(Constants.TYPE_STRING_BUFFER);
  • e.dup();
  • e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
  • for (int i = 0; i < parameterTypes.length; i++) {
  • if (i > 0) {
  • e.push(", ");
  • e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
  • }
  • e.load_this();
  • e.getfield(getFieldName(i));
  • EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizer);
  • }
  • e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
  • e.return_value();
  • e.end_method();
  • ce.end_class();
  • }

该方法大量使用了ASM提供的API,我们无需关注细节(ASM细节内容非常多,涉及了大量对字节码文件的直接操作),只需要知道它为我们需要的类生成了默认构造函数、有参构造方法、equals()方法、hashCode()方法、toString()方法和newInstance()工厂方法,其中最重要的是newInstance()工厂方法,后面会使用该方法创建实例对象。

如果我们指定了DebuggingClassWriter.DEBUG_LOCATION_PROPERTY路径,那么这里生成的Class字节码文件会在该路径下生成一份;以当前为例,我们指定了CGLIB产生的Class文件的存放目录为/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/,在该目录下使用tree命令查看目录结构,可以发现在com/coderap/proxy/cglib目录下生成了6个Class字节码文件:

  • $> tree .
  • .
  • ├── com
  • │   └── coderap
  • │   └── proxy
  • │   └── cglib
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$48029d80.class
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26.class
  • │   ├── Bugatti$$FastClassByCGLIB$$e6a580a8.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705$$FastClassByCGLIB$$edb3e882.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705.class
  • │   └── Ferrari$$FastClassByCGLIB$$9f935905.class
  • └── net
  • └── sf
  • └── cglib
  • ├── core
  • │   └── MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7.class
  • └── proxy
  • └── Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class
  • 9 directories, 8 files

从前面得到的最终的字节码文件命名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$ + key的hashCode可知,其中./net/sf/cglib/proxy/路径下的EnhancerEnhancerKeyKeyFactoryByCGLIB$7fb24d72.class即是生成的Class字节码文件,通过反编译我们可以得到如下源码:

  • //
  • // Source code recreated from a .class file by IntelliJ IDEA
  • // (powered by Fernflower decompiler)
  • //
  • package net.sf.cglib.proxy;
  • import net.sf.cglib.core.KeyFactory;
  • import net.sf.cglib.proxy.Enhancer.EnhancerKey;
  • import org.objectweb.asm.Type;
  • public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72 extends KeyFactory implements EnhancerKey {
  • private final String FIELD_0;
  • private final String[] FIELD_1;
  • private final CallbackFilter FIELD_2;
  • private final Type[] FIELD_3;
  • private final boolean FIELD_4;
  • private final boolean FIELD_5;
  • private final Long FIELD_6;
  • public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72() {
  • }
  • public Object newInstance(String var1, String[] var2, CallbackFilter var3, Type[] var4, boolean var5, boolean var6, Long var7) {
  • return new Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(var1, var2, var3, var4, var5, var6, var7);
  • }
  • public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(String var1, String[] var2, CallbackFilter var3, Type[] var4, boolean var5, boolean var6, Long var7) {
  • this.FIELD_0 = var1;
  • this.FIELD_1 = var2;
  • this.FIELD_2 = var3;
  • this.FIELD_3 = var4;
  • this.FIELD_4 = var5;
  • this.FIELD_5 = var6;
  • this.FIELD_6 = var7;
  • }
  • public int hashCode() {
  • int var10000 = 8095873 * 69403 + (this.FIELD_0 != null ? this.FIELD_0.hashCode() : 0);
  • String[] var10001 = this.FIELD_1;
  • if (this.FIELD_1 != null) {
  • String[] var1 = var10001;
  • for(int var2 = 0; var2 < var1.length; ++var2) {
  • var10000 = var10000 * 69403 + (var1[var2] != null ? var1[var2].hashCode() : 0);
  • }
  • }
  • var10000 = var10000 * 69403 + (this.FIELD_2 != null ? this.FIELD_2.hashCode() : 0);
  • Type[] var5 = this.FIELD_3;
  • if (this.FIELD_3 != null) {
  • Type[] var3 = var5;
  • for(int var4 = 0; var4 < var3.length; ++var4) {
  • var10000 = var10000 * 69403 + (var3[var4] != null ? var3[var4].hashCode() : 0);
  • }
  • }
  • return ((var10000 * 69403 + (this.FIELD_4 ^ 1)) * 69403 + (this.FIELD_5 ^ 1)) * 69403 + (this.FIELD_6 != null ? this.FIELD_6.hashCode() : 0);
  • }
  • public boolean equals(Object var1) {
  • if (var1 instanceof Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72) {
  • String var10000 = this.FIELD_0;
  • String var10001 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_0;
  • String var10002 = this.FIELD_0;
  • if (((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_0 == null) {
  • if (var10002 != null) {
  • return false;
  • }
  • } else if (var10002 == null || !var10000.equals(var10001)) {
  • return false;
  • }
  • String[] var8 = this.FIELD_1;
  • String[] var10 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_1;
  • String[] var15 = this.FIELD_1;
  • if (((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_1 == null) {
  • if (var15 != null) {
  • return false;
  • }
  • } else {
  • label178: {
  • if (var15 != null) {
  • if (var10.length == var8.length) {
  • String[] var2 = var10;
  • String[] var3 = var8;
  • int var4 = 0;
  • while(true) {
  • if (var4 >= var2.length) {
  • break label178;
  • }
  • var10000 = var2[var4];
  • var10001 = var3[var4];
  • if (var3[var4] == null) {
  • if (var10000 != null) {
  • return false;
  • }
  • } else if (var10000 == null || !var10000.equals(var10001)) {
  • return false;
  • }
  • ++var4;
  • }
  • }
  • }
  • return false;
  • }
  • }
  • CallbackFilter var9 = this.FIELD_2;
  • CallbackFilter var13 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_2;
  • CallbackFilter var17 = this.FIELD_2;
  • if (((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_2 == null) {
  • if (var17 != null) {
  • return false;
  • }
  • } else if (var17 == null || !var9.equals(var13)) {
  • return false;
  • }
  • Type[] var11 = this.FIELD_3;
  • Type[] var16 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_3;
  • Type[] var19 = this.FIELD_3;
  • if (((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_3 == null) {
  • if (var19 != null) {
  • return false;
  • }
  • } else {
  • if (var19 == null) {
  • return false;
  • }
  • if (var16.length != var11.length) {
  • return false;
  • }
  • Type[] var5 = var16;
  • Type[] var6 = var11;
  • for(int var7 = 0; var7 < var5.length; ++var7) {
  • Type var12 = var5[var7];
  • Type var18 = var6[var7];
  • if (var6[var7] == null) {
  • if (var12 != null) {
  • return false;
  • }
  • } else if (var12 == null || !var12.equals(var18)) {
  • return false;
  • }
  • }
  • }
  • if (this.FIELD_4 == ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_4 && this.FIELD_5 == ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_5) {
  • Long var14 = this.FIELD_6;
  • Long var20 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_6;
  • Long var21 = this.FIELD_6;
  • if (((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72)var1).FIELD_6 == null) {
  • if (var21 == null) {
  • return true;
  • }
  • } else if (var21 != null && var14.equals(var20)) {
  • return true;
  • }
  • }
  • }
  • return false;
  • }
  • public String toString() {
  • StringBuffer var10000 = new StringBuffer();
  • var10000 = (this.FIELD_0 != null ? var10000.append(this.FIELD_0.toString()) : var10000.append("null")).append(", ");
  • String[] var10001 = this.FIELD_1;
  • if (this.FIELD_1 != null) {
  • var10000 = var10000.append("{");
  • String[] var1 = var10001;
  • for(int var2 = 0; var2 < var1.length; ++var2) {
  • var10000 = (var1[var2] != null ? var10000.append(var1[var2].toString()) : var10000.append("null")).append(", ");
  • }
  • var10000.setLength(var10000.length() - 2);
  • var10000 = var10000.append("}");
  • } else {
  • var10000 = var10000.append("null");
  • }
  • var10000 = var10000.append(", ");
  • var10000 = (this.FIELD_2 != null ? var10000.append(this.FIELD_2.toString()) : var10000.append("null")).append(", ");
  • Type[] var7 = this.FIELD_3;
  • if (this.FIELD_3 != null) {
  • var10000 = var10000.append("{");
  • Type[] var3 = var7;
  • for(int var4 = 0; var4 < var3.length; ++var4) {
  • var10000 = (var3[var4] != null ? var10000.append(var3[var4].toString()) : var10000.append("null")).append(", ");
  • }
  • var10000.setLength(var10000.length() - 2);
  • var10000 = var10000.append("}");
  • } else {
  • var10000 = var10000.append("null");
  • }
  • var10000 = var10000.append(", ").append(this.FIELD_4).append(", ").append(this.FIELD_5).append(", ");
  • return (this.FIELD_6 != null ? var10000.append(this.FIELD_6.toString()) : var10000.append("null")).toString();
  • }
  • }

从反编译得到的源码可以看到,默认构造函数、有参构造方法、equals()方法、hashCode()方法、toString()方法和newInstance()工厂方法该类都已经生成好了。我们主要关注newInstance()工厂方法,它调用有参构造方法生成了一个Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72实例:

  • public Object newInstance(String var1, String[] var2, CallbackFilter var3, Type[] var4, boolean var5, boolean var6, Long var7) {
  • return new Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(var1, var2, var3, var4, var5, var6, var7);
  • }

绕了这么大一圈,我们终于得到了生成的KeyFactory类,让我们回到AbstractClassGenerator类的create(Object)方法中,在获取了生成的字节码文件的byte数组后,会通过ReflectUtils.defineClass(className, b, loader)使用反射得到相应的实例,源码如下:

  • byte[] b = strategy.generate(this);
  • String className = ClassNameReader.getClassName(new ClassReader(b));
  • // 将className放入NAME_KEY对应的Set中
  • getClassNameCache(loader).add(className);
  • // 根据返回的字节码生成类
  • gen = ReflectUtils.defineClass(className, b, loader);

其中ReflectUtils.defineClass(String className, byte[] b, ClassLoader loader)的原理其实是通过反射调用ClassLoader的defineClass()方法来创建类的:

  • public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
  • Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
  • Class c = (Class)DEFINE_CLASS.invoke(loader, args);
  • // Force static initializers to run.
  • Class.forName(className, true, loader);
  • return c;
  • }

最终得到Class类对象之后,会使用firstInstance(gen)将Class对象传入,创建对应的实例,此处使用的firstInstance(Class)来自于Generator类:

  • // Generator类的firstInstance(Class),调用了ReflectUtils类的newInstance(Class)方法
  • protected Object firstInstance(Class type) {
  • return ReflectUtils.newInstance(type);
  • }
  • // ReflectUtils类newInstance(Class)的相关方法
  • public static Object newInstance(Class type) {
  • return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
  • }
  • public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
  • return newInstance(getConstructor(type, parameterTypes), args);
  • }
  • public static Object newInstance(final Constructor cstruct, final Object[] args) {
  • boolean flag = cstruct.isAccessible();
  • try {
  • // 设置构造方法的可见性
  • cstruct.setAccessible(true);
  • // 根据构造方法创建对象
  • Object result = cstruct.newInstance(args);
  • return result;
  • } catch (InstantiationException e) {
  • throw new CodeGenerationException(e);
  • } catch (IllegalAccessException e) {
  • throw new CodeGenerationException(e);
  • } catch (InvocationTargetException e) {
  • throw new CodeGenerationException(e.getTargetException());
  • } finally {
  • cstruct.setAccessible(flag);
  • }
  • }

此时,我们终于分析完KEY_FACTORY是如何得到的,最终它是一个Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72类对象。

3.3. 代理类的生成

我们接着分析Enhancer类中的createHelper()方法,回顾一下源码:

  • private Object createHelper() {
  • validate();
  • if (superclass != null) {
  • setNamePrefix(superclass.getName());
  • } else if (interfaces != null) {
  • setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
  • }
  • // 注意,此时superClass是我们想要得到的目标类
  • return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
  • ReflectUtils.getNames(interfaces),
  • filter,
  • callbackTypes,
  • useFactory,
  • interceptDuringConstruction,
  • serialVersionUID));
  • }

从源码可知,此时会调用KEY_FACTORY(也即是Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72类)的newInstance(...)方法,得到的是一个Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72对象,然后又将其传给了super.create(Object)方法,而Enhancer类的父类,就是前面分析过的AbstractClassGenerator类,create(Object)方法也就是是前面分析过的create(Object)方法,不同的是,这一次传入的key参数是一个Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72实例。

由于这一次的key参数改为了Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72实例,因此在缓存中并不能找到相应的类对象(前面缓存的是KeyFactory类对象),同时也无法使用ClassLoader直接加载,很显然,这一次又会进行Class对象生成操作;与上一次不同的是,这一次将会使用Enhancer实例的generateClass(ClassVisitor)方法,源码如下:

  • public void generateClass(ClassVisitor v) throws Exception {
  • // 获取superClass类,也即是我们指定的目标类,如果没有就使用Object作为superClass类
  • Class sc = (superclass == null) ? Object.class : superclass;
  • if (TypeUtils.isFinal(sc.getModifiers()))
  • throw new IllegalArgumentException("Cannot subclass final class " + sc);
  • // 构造方法相关
  • 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);
  • 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);
  • List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
  • e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_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);
  • }
  • // 生成方法
  • emitMethods(e, methods, actualMethods);
  • // 生成构造方法
  • emitConstructors(e, constructorInfo);
  • emitSetThreadCallbacks(e);
  • // 绑定静态callback
  • emitSetStaticCallbacks(e);
  • // 绑定callback
  • emitBindCallbacks(e);
  • if (useFactory) {
  • int[] keys = getCallbackKeys();
  • emitNewInstanceCallbacks(e);
  • emitNewInstanceCallback(e);
  • emitNewInstanceMultiarg(e, constructorInfo);
  • emitGetCallback(e, keys);
  • emitSetCallback(e, keys);
  • emitGetCallbacks(e);
  • emitSetCallbacks(e);
  • }
  • e.end_class();
  • }

同时,这一次使用DefaultNamingPolicy命名策略的getClassName(String prefix, String source, Object key, Predicate names)方法生成的文件名时,prefix传入的是在使用Enhancer对象的setSuperclass(Class)方法时传入的superClass字段,涉及到的相关方法的源码如下:

  • public void setSuperclass(Class superclass) {
  • if (superclass != null && superclass.isInterface()) {
  • // 如果superClass不为空且是接口,就用Class数组来装载它
  • setInterfaces(new Class[]{ superclass });
  • } else if (superclass != null && superclass.equals(Object.class)) {
  • // 如果superClass是Object类,则将superClass置为null
  • // affects choice of ClassLoader
  • this.superclass = null;
  • } else {
  • // 否则记录superClass
  • this.superclass = superclass;
  • }
  • }
  • private Object createHelper() {
  • validate();
  • if (superclass != null) {
  • // 如果superClass不为空,则设置namePrefix为superClass的全限定类名
  • setNamePrefix(superclass.getName());
  • } else if (interfaces != null) {
  • setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
  • }
  • return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
  • ReflectUtils.getNames(interfaces),
  • filter,
  • callbackTypes,
  • useFactory,
  • interceptDuringConstruction,
  • serialVersionUID));
  • }

以生成Bugatti类的代理类为例,此时superClass即为Bugatti的全限定名——com.coderap.proxy.cglib.Bugatti,因此根据前面提到的Class文件名生成策略被代理类名 + "$$" + Class Generator Name + "ByCGLIB" + "$$" + key的hashCode规则,生成的Bugatti类的代理类Class文件名应该是com.coderap.proxy.cglib.Bugatti$$EnhancerByCGLIB$$ + key的hashCode

这一次则可以生成我们想要的目标类的代理类对象了,最后又会调用firstInstance(gen)并返回,这里的firstInstance(Class)则是由AbstractClassGenerator的子类Enhancer实现的:

  • protected Object firstInstance(Class type) throws Exception {
  • // 是否仅生产类对象
  • if (classOnly) {
  • return type;
  • } else {
  • // 如果要生成实例对象,使用反射实现
  • return createUsingReflection(type);
  • }
  • }
  • private Object createUsingReflection(Class type) {
  • setThreadCallbacks(type, callbacks);
  • try {
  • if (argumentTypes != null) {
  • // 有指定参数和参数类型
  • return ReflectUtils.newInstance(type, argumentTypes, arguments);
  • } else {
  • // 没有参数和参数类型
  • return ReflectUtils.newInstance(type);
  • }
  • }finally{
  • // clear thread callbacks to allow them to be gc'd
  • setThreadCallbacks(type, null);
  • }
  • }

可以发现,这里的firstInstance(Class)与前面讲解的一样,同样是使用反射进行实例的创建。

4. 分析生成的代理类

在上面测试代码中,我们指定了CGLIB产生的Class文件的存放目录为/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/,在该目录下生成了6个Class字节码文件:

  • $> tree .
  • .
  • ├── com
  • │   └── coderap
  • │   └── proxy
  • │   └── cglib
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$48029d80.class
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26.class
  • │   ├── Bugatti$$FastClassByCGLIB$$e6a580a8.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705$$FastClassByCGLIB$$edb3e882.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705.class
  • │   └── Ferrari$$FastClassByCGLIB$$9f935905.class
  • └── net
  • └── sf
  • └── cglib
  • ├── core
  • │   └── MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7.class
  • └── proxy
  • └── Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class
  • 9 directories, 8 files

以Bugatti类生成的Class字节码文件为例,其中BugattiEnhancerByCGLIB4ddb6f26.class文件即是CGLib为Bugatti类生成的代理类,通过反编译,我们可以得到它的原始代码,内容如下:

  • //
  • // Source code recreated from a .class file by IntelliJ IDEA
  • // (powered by Fernflower decompiler)
  • //
  • package com.coderap.proxy.cglib;
  • import java.lang.reflect.Method;
  • import net.sf.cglib.core.ReflectUtils;
  • import net.sf.cglib.core.Signature;
  • import net.sf.cglib.proxy.Callback;
  • import net.sf.cglib.proxy.Factory;
  • import net.sf.cglib.proxy.MethodInterceptor;
  • import net.sf.cglib.proxy.MethodProxy;
  • public class Bugatti$$EnhancerByCGLIB$$4ddb6f26 extends Bugatti implements Factory {
  • private boolean CGLIB$BOUND;
  • private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
  • private static final Callback[] CGLIB$STATIC_CALLBACKS;
  • private MethodInterceptor CGLIB$CALLBACK_0; // 拦截器
  • private static final Method CGLIB$run$0$Method; // 被代理的方法
  • private static final MethodProxy CGLIB$run$0$Proxy; // 代理方法
  • private static final Object[] CGLIB$emptyArgs;
  • private static final Method CGLIB$getInfo$1$Method; // 被代理的方法
  • private static final MethodProxy CGLIB$getInfo$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 {
  • CGLIB$STATICHOOK1();
  • }
  • static void CGLIB$STATICHOOK1() {
  • CGLIB$THREAD_CALLBACKS = new ThreadLocal();
  • CGLIB$emptyArgs = new Object[0];
  • Class var0 = Class.forName("com.coderap.proxy.cglib.Bugatti$$EnhancerByCGLIB$$4ddb6f26"); // 代理类
  • Class var1; // 目标类
  • Method[] var10000 = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
  • CGLIB$finalize$2$Method = var10000[0];
  • CGLIB$finalize$2$Proxy = MethodProxy.create(var1, var0, "()V", "finalize", "CGLIB$finalize$2");
  • CGLIB$equals$3$Method = var10000[1];
  • CGLIB$equals$3$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3");
  • CGLIB$toString$4$Method = var10000[2];
  • CGLIB$toString$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$4");
  • CGLIB$hashCode$5$Method = var10000[3];
  • CGLIB$hashCode$5$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$5");
  • CGLIB$clone$6$Method = var10000[4];
  • CGLIB$clone$6$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$6");
  • // 获取被代理类的方法
  • var10000 = ReflectUtils.findMethods(new String[]{"run", "()V", "getInfo", "()Ljava/lang/String;"}, (var1 = Class.forName("com.coderap.proxy.cglib.Bugatti")).getDeclaredMethods());
  • CGLIB$run$0$Method = var10000[0];
  • // 初始化代理类的run方法
  • CGLIB$run$0$Proxy = MethodProxy.create(var1, var0, "()V", "run", "CGLIB$run$0");
  • CGLIB$getInfo$1$Method = var10000[1];
  • // 代理类的getInfo方法
  • CGLIB$getInfo$1$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "getInfo", "CGLIB$getInfo$1");
  • }
  • // 代理方法,在使用methodProxy.invokeSuper(...)时会调用该方法
  • final void CGLIB$run$0() {
  • super.run();
  • }
  • /**
  • * 目标类的被代理方法,如果直接使用methodProxy.invoke()时会调用该方法
  • * 如果在拦截器中调用methodProxy.invoke()会陷入死循环,
  • * 因为在该方法中会一直调用拦截器
  • */
  • public final void run() {
  • 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$run$0$Method, CGLIB$emptyArgs, CGLIB$run$0$Proxy);
  • } else {
  • super.run();
  • }
  • }
  • // 代理方法,在使用methodProxy.invokeSuper时会调用该方法
  • final String CGLIB$getInfo$1() {
  • return super.getInfo();
  • }
  • // 目标类的被代理方法
  • public final String getInfo() {
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • CGLIB$BIND_CALLBACKS(this);
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • return var10000 != null ? (String)var10000.intercept(this, CGLIB$getInfo$1$Method, CGLIB$emptyArgs, CGLIB$getInfo$1$Proxy) : super.getInfo();
  • }
  • final void CGLIB$finalize$2() throws Throwable {
  • super.finalize();
  • }
  • protected final void finalize() throws Throwable {
  • 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$finalize$2$Method, CGLIB$emptyArgs, CGLIB$finalize$2$Proxy);
  • } else {
  • super.finalize();
  • }
  • }
  • final boolean CGLIB$equals$3(Object var1) {
  • return super.equals(var1);
  • }
  • public final boolean equals(Object var1) {
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • CGLIB$BIND_CALLBACKS(this);
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • if (var10000 != null) {
  • Object var2 = var10000.intercept(this, CGLIB$equals$3$Method, new Object[]{var1}, CGLIB$equals$3$Proxy);
  • return var2 == null ? false : (Boolean)var2;
  • } else {
  • return super.equals(var1);
  • }
  • }
  • final String CGLIB$toString$4() {
  • return super.toString();
  • }
  • public final String toString() {
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • CGLIB$BIND_CALLBACKS(this);
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$4$Method, CGLIB$emptyArgs, CGLIB$toString$4$Proxy) : super.toString();
  • }
  • final int CGLIB$hashCode$5() {
  • return super.hashCode();
  • }
  • public final int hashCode() {
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • CGLIB$BIND_CALLBACKS(this);
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • if (var10000 != null) {
  • Object var1 = var10000.intercept(this, CGLIB$hashCode$5$Method, CGLIB$emptyArgs, CGLIB$hashCode$5$Proxy);
  • return var1 == null ? 0 : ((Number)var1).intValue();
  • } else {
  • return super.hashCode();
  • }
  • }
  • final Object CGLIB$clone$6() throws CloneNotSupportedException {
  • return super.clone();
  • }
  • protected final Object clone() throws CloneNotSupportedException {
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • CGLIB$BIND_CALLBACKS(this);
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • return var10000 != null ? var10000.intercept(this, CGLIB$clone$6$Method, CGLIB$emptyArgs, CGLIB$clone$6$Proxy) : super.clone();
  • }
  • public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
  • String var10000 = var0.toString();
  • switch(var10000.hashCode()) {
  • case -1574182249:
  • if (var10000.equals("finalize()V")) {
  • return CGLIB$finalize$2$Proxy;
  • }
  • break;
  • case -919875318:
  • if (var10000.equals("run()V")) {
  • return CGLIB$run$0$Proxy;
  • }
  • break;
  • case -508378822:
  • if (var10000.equals("clone()Ljava/lang/Object;")) {
  • return CGLIB$clone$6$Proxy;
  • }
  • break;
  • case -244718353:
  • if (var10000.equals("getInfo()Ljava/lang/String;")) {
  • return CGLIB$getInfo$1$Proxy;
  • }
  • break;
  • case 1826985398:
  • if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
  • return CGLIB$equals$3$Proxy;
  • }
  • break;
  • case 1913648695:
  • if (var10000.equals("toString()Ljava/lang/String;")) {
  • return CGLIB$toString$4$Proxy;
  • }
  • break;
  • case 1984935277:
  • if (var10000.equals("hashCode()I")) {
  • return CGLIB$hashCode$5$Proxy;
  • }
  • }
  • return null;
  • }
  • public Bugatti$$EnhancerByCGLIB$$4ddb6f26(String var1) {
  • super(var1);
  • 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) {
  • Bugatti$$EnhancerByCGLIB$$4ddb6f26 var1 = (Bugatti$$EnhancerByCGLIB$$4ddb6f26)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) {
  • // $FF: Couldn't be decompiled
  • }
  • public Object newInstance(Callback var1) {
  • // $FF: Couldn't be decompiled
  • }
  • public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
  • CGLIB$SET_THREAD_CALLBACKS(var3);
  • Bugatti$$EnhancerByCGLIB$$4ddb6f26 var10000 = new Bugatti$$EnhancerByCGLIB$$4ddb6f26;
  • switch(var1.length) {
  • case 1:
  • if (var1[0].getName().equals("java.lang.String")) {
  • var10000.<init>((String)var2[0]);
  • 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];
  • }
  • }

从反编译的接口可知,该类继承了Bugatti类;同时,该类的属性列表中,我们可以观察到MethodInterceptor类型的CGLIB$CALLBACK_0属性,同时还有针对run()getInfo()finalize()equals()toString()hashCode()clone()等被代理方法和其代理方法。:

  • private MethodInterceptor CGLIB$CALLBACK_0; // 拦截器
  • private static final Method CGLIB$run$0$Method; // 被代理的方法
  • private static final MethodProxy CGLIB$run$0$Proxy; // 代理方法
  • ...
  • private static final Method CGLIB$getInfo$1$Method; // 被代理的方法
  • private static final MethodProxy CGLIB$getInfo$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; // 代理方法

我们继续观察该类的静态代码块,可以发现其中调用了CGLIB$STATICHOOK1()方法,这个方法主要用于完成对类中各类属性的初始化工作,这里我们主要关注run()getInfo()两个我们自己编写的方法相关的代码:

  • Class var0 = Class.forName("com.coderap.proxy.cglib.Bugatti$$EnhancerByCGLIB$$4ddb6f26"); // 代理类
  • Class var1; // 目标类
  • Method[] var10000 = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());// 获取被代理类的方法
  • var10000 = ReflectUtils.findMethods(new String[]{"run", "()V", "getInfo", "()Ljava/lang/String;"}, (var1 = Class.forName("com.coderap.proxy.cglib.Bugatti")).getDeclaredMethods());
  • CGLIB$run$0$Method = var10000[0];
  • // 初始化代理类的run方法
  • CGLIB$run$0$Proxy = MethodProxy.create(var1, var0, "()V", "run", "CGLIB$run$0");
  • CGLIB$getInfo$1$Method = var10000[1];
  • // 代理类的getInfo方法
  • CGLIB$getInfo$1$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "getInfo", "CGLIB$getInfo$1");

可以发现,在上面的代码中,首先通过Class.forName(String)方法加载了代理类com.coderap.proxy.cglib.BugattiEnhancerByCGLIB4ddb6f26,也即是BugattiEnhancerByCGLIB4ddb6f26当前类,然后通过CGLIB提供的工具类ReflectUtils的findMethods(String[] namesAndDescriptors, Method[] methods)方法获取了com.coderap.proxy.cglib.Bugatti原始被代理类中的run()getInfo()两个原始方法的定义;工具类ReflectUtils的findMethods(String[] namesAndDescriptors, Method[] methods)方法的代码如下:

  • public static Method[] findMethods(String[] namesAndDescriptors, Method[] methods) {
  • Map map = new HashMap();
  • // 将传入的所有method对象装入字典map,使用ASM框架获取的method描述作为键,method对象作为值
  • for(int i = 0; i < methods.length; ++i) {
  • Method method = methods[i];
  • map.put(method.getName() + Type.getMethodDescriptor(method), method);
  • }
  • // 定义一个Method数组,用于放置筛选出的Method方法
  • Method[] result = new Method[namesAndDescriptors.length / 2];
  • for(int i = 0; i < result.length; ++i) {
  • result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]);
  • if (result[i] == null) {
  • ;
  • }
  • }
  • return result;
  • }

注:这里补充一下关于Class字节码的知识;在Java编译器产出的Class字节码文件中,对Java类型的定义是通过简单的字符来表示的;在上述代码ReflectUtils.findMethods(new String[]{"run", "()V", "getInfo", "()Ljava/lang/String;"}, (var1 = Class.forName("com.coderap.proxy.cglib.Bugatti")).getDeclaredMethods());中我们可以发现第一个参数传入的是一个String数组,内容为{"run", "()V", "getInfo", "()Ljava/lang/String;"},该数组内其实列出了run()getInfo()两个方法和它们的签名类型,run()方法是无参数无返回值的,所以其签名类型为()V,而getInfo()方法是无参数但有一个String类型的返回值的,所以其签名为()Ljava/lang/String;;这里有疑问的读者可以阅读Java虚拟机系列文章,在Java虚拟机15——类文件结构一文的7. 字段表集合`一节有详细介绍。

该类的实现其实是比较简单的,通过ASM框架提供的功能来获取原始被代理类com.coderap.proxy.cglib.Bugatti中所有方法的Method对象,并装入字典map中,然后根据传入的namesAndDescriptors数组内容,从字典map中获取对应的Method对象。

在获取了run()getInfo()两个原始方法之后,分别将代表它们的Method对象使用属性CGLIB$run$0$MethodCGLIB$getInfo$1$Method记录下来。同时通过CGLIB提供的MethodProxy的create(Class, Class, String, String, String)方法创建两个方法的MethodProxy方法代理对象,并分别使用属性CGLIB$run$0$ProxyCGLIB$getInfo$1$Proxy记录;代码如下:

  • CGLIB$run$0$Proxy = MethodProxy.create(var1, var0, "()V", "run", "CGLIB$run$0");
  • CGLIB$getInfo$1$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "getInfo", "CGLIB$getInfo$1");

需要注意的是,在调用MethodProxy的create(Class var1, Class var0, String, String, String)方法时,传入的前两个参数var1var0已经被置为了com.coderap.proxy.cglib.BugattiEnhancerByCGLIB4ddb6f26类对象和com.coderap.proxy.cglib.Bugatti类对象。

我们继续深入MethodProxy的create(Class, Class, String, String, String)方法的源代码:

  • public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
  • // 创建MethodProxy对象
  • MethodProxy proxy = new MethodProxy();
  • // 关联原始方法
  • proxy.sig1 = new Signature(name1, desc);
  • // 关联代理方法
  • proxy.sig2 = new Signature(name2, desc);
  • // 使用代理类对象和被代理类对象创建CreateInfo对象
  • proxy.createInfo = new MethodProxy.CreateInfo(c1, c2);
  • return proxy;
  • }
  • 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;
  • // 这里获取的fromEnhancer其实是当前Enhancer实例
  • AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
  • // 如果fromEnhancer不为null,则获取fromEnhancer的命名策略器、生成策略器及是否尝试类加载器加载配置
  • if (fromEnhancer != null) {
  • this.namingPolicy = fromEnhancer.getNamingPolicy();
  • this.strategy = fromEnhancer.getStrategy();
  • this.attemptLoad = fromEnhancer.getAttemptLoad();
  • }
  • }
  • }

MethodProxy的CreateInfo(Class, Class, String, String, String)方法最终产生了一个MethodProxy对象,使用属性sig1sig2对原始方法和代理方法进行记录和关联,构造了一个CreateInfo对象对代理类和被代理类进行记录和关联,也就是说,通过MethodProxy对象我们可以直接获取原始类及代理类相关的信息。

我们关注BugattiEnhancerByCGLIB4ddb6f26类的run()方法;由于该类是包装了目标类Bugatti的代理类,因此最终在调用run()方法时其实是调用该类的run()方法,源码如下:

  • /**
  • * 目标类的被代理方法,如果直接使用methodProxy.invoke()时会调用该方法
  • * 如果在拦截器中调用methodProxy.invoke()会陷入死循环,
  • * 因为在该方法中会一直调用拦截器
  • */
  • public final void run() {
  • // 得到MethodInterceptor
  • MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
  • if (this.CGLIB$CALLBACK_0 == null) {
  • // 如果MethodInterceptor为null,就使用CGLIB$BIND_CALLBACKS(Object)处理
  • CGLIB$BIND_CALLBACKS(this);
  • // 获取新的MethodInterceptor
  • var10000 = this.CGLIB$CALLBACK_0;
  • }
  • if (var10000 != null) {
  • /**
  • * 如果MethodInterceptor不为null,则调用MethodInterceptor拦截器的intercept()拦截方法
  • * 注意,
  • * 此时的第一个参数为代理类对象,
  • * 第二个参数为被代理的方法,即CGLIB$run$0$Method
  • * 第三个参数是执行方法需要的参数,没有参数,所以为CGLIB$emptyArgs
  • * 第四个参数为MethodProxy,这里是CGLIB$run$0$Proxy,即前面使用MethodProxy.create()方法创建的
  • */
  • var10000.intercept(this, CGLIB$run$0$Method, CGLIB$emptyArgs, CGLIB$run$0$Proxy);
  • } else {
  • // 否则说明没有拦截器,此时直接调用父类的run()方法
  • super.run();
  • }
  • }
  • private static final void CGLIB$BIND_CALLBACKS(Object var0) {
  • Bugatti$$EnhancerByCGLIB$$4ddb6f26 var1 = (Bugatti$$EnhancerByCGLIB$$4ddb6f26)var0;
  • if (!var1.CGLIB$BOUND) {
  • // 如果没有进行callback绑定
  • // 首先将CGLIB$BOUND标志位置为true
  • var1.CGLIB$BOUND = true;
  • // 获取ThreadLocal对象CGLIB$THREAD_CALLBACKS中的Callback
  • Object var10000 = CGLIB$THREAD_CALLBACKS.get();
  • if (var10000 == null) {
  • /**
  • * 如果ThreadLocal对象CGLIB$THREAD_CALLBACKS中的Callback也为null
  • * 就尝试使用CGLIB$STATIC_CALLBACKS静态callback
  • */
  • var10000 = CGLIB$STATIC_CALLBACKS;
  • if (CGLIB$STATIC_CALLBACKS == null) {
  • // 如果静态callback也为null,表示没有callback,则直接返回
  • return;
  • }
  • }
  • // 否则将CGLIB$CALLBACK_0设置为var10000中的第一个元素
  • var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
  • }
  • }

从源码可知,最后调用的其实是我们指定的MethodInterceptor对象的intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy)方法;而在我们的例子中,使用的MethodInterceptor是实现了MethodInterceptor接口的自定义SpeedTestMethodInterceptor对象。

5. MethodProxy分析

在上面的分析中我们已经知道,生成的动态代理类最终会调用开发者指定的MethodInterceptor实例的intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy)方法,这个方法是由开发者自己实现的,在我们的例子中,最终会通过methodProxy.invokeSuper(object, objects)来实现目标类方法真正的调用。methodProxy是一个MethodProxy实例,前面有提到过它的产生,它关联了目标类和代理类以及相应的目标方法和代理方法。因此接下来我们分析一下MethodProxy类实现。

首先从入口分析,Object invokeSuper(Object obj, Object[] args)方法的源码如下:

  • public Object invokeSuper(Object obj, Object[] args) throws Throwable {
  • try {
  • // init操作会处理FastClass相关的配置,在后面会详细介绍
  • init();
  • // 获取FastClassInfo对象fci
  • FastClassInfo fci = fastClassInfo;
  • // 使用fci进行方法调用,f2是代理类的方法,i2是代理类方法的索引,后面会详解
  • return fci.f2.invoke(fci.i2, obj, args);
  • } catch (InvocationTargetException e) {
  • throw e.getTargetException();
  • }
  • }

上面的代码其实引入了一种FastClass机制,FastClass机制会对一个类的方法建立索引,通过索引来直接调用相应的方法。我们先关注上面调用的init()方法源码如下:

  • private void init() {
  • /*
  • * Using a volatile invariant allows us to initialize the FastClass and
  • * method index pairs atomically.
  • *
  • * Double-checked locking is safe with volatile in Java 5. Before 1.5 this
  • * code could allow fastClassInfo to be instantiated more than once, which
  • * appears to be benign.
  • */
  • // DCL双重检查锁,单例模式,确保fastClassInfo只会被实例化一次
  • if (fastClassInfo == null) {
  • synchronized (initLock) {
  • if (fastClassInfo == null) {
  • // 如果fastClassInfo为null,说明目前还没有生成目标类的FastClass代理类
  • // 获取createInfo对象,该对象存储了目标类和代理类的相关信息
  • CreateInfo ci = createInfo;
  • // 创建新的FastClassInfo实例
  • FastClassInfo fci = new FastClassInfo();
  • // 根据传入的createInfo信息和类对象生成代理类对应的Class字节码文件,见后面分析
  • fci.f1 = helper(ci, ci.c1);
  • // 根据传入的createInfo信息和类对象生成目标类对应的Class字节码文件,见后面分析
  • fci.f2 = helper(ci, ci.c2);
  • /**
  • * 获取当前方法在f1、f2中的签名,得到一个index
  • * 方法与签名、index是一一对应的关系,可以根据index映射对应类的对应方法
  • */
  • fci.i1 = fci.f1.getIndex(sig1);
  • fci.i2 = fci.f2.getIndex(sig2);
  • fastClassInfo = fci;
  • createInfo = null;
  • }
  • }
  • }
  • }
  • // FastClassInfo是MethodProxy的静态内部类
  • private static class FastClassInfo {
  • FastClass f1; // 目标类的FastClass
  • FastClass f2; // 代理类的FastClass
  • int i1; // f1对应的索引,后面讲解
  • int i2; // f2对应的索引,后面讲解
  • }

其中helper(CreateInfo, Class)方法源码如下:

  • private static FastClass helper(CreateInfo ci, Class type) {
  • // 根据ci得到该方法的委托类,实现类,分别生成这两个类的fastClass
  • // 生成FastClass内部的Generator实例
  • FastClass.Generator g = new FastClass.Generator();
  • // 设置类型
  • g.setType(type);
  • // 记录目标类的类加载器
  • g.setClassLoader(ci.c2.getClassLoader());
  • // 设置命名策略
  • g.setNamingPolicy(ci.namingPolicy);
  • // 设置生成策略
  • g.setStrategy(ci.strategy);
  • // 设置是否尝试使用类加载器加载
  • g.setAttemptLoad(ci.attemptLoad);
  • // 使用FastClass.Generator对象生成FastClass
  • return g.create();
  • }
  • public FastClass create() {
  • setNamePrefix(type.getName());
  • return (FastClass)super.create(type.getName());
  • }

helper(CreateInfo, Class)方法的作用其实比较简单,它会从ci中获取目标类的类加载器,生成代理类时使用的命名策略、生成策略等信息,然后使用FastClass的内部类Generator实例生成FastClass并返回。

由于此时使用的命名策略其实是生产代理类时使用的命名策略,所以根据前面提到的Class文件名生成策略被代理类名 + "$$" + Class Generator Name + "ByCGLIB" + "$$" + key的hashCode规则,helper(ci, ci.c1)方法中生成的FastClass代理类Class文件名应该是com.coderap.proxy.cglib.Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$ + key的hashCodehelper(ci, ci.c2)方法中生成的FastClass代理类Class文件名应该是com.coderap.proxy.cglib.Bugatti$$FastClassByCGLIB$$ + key的hashCode。两次helper(CreateInfo, Class)最终会生成的目标类和代理类的FastClass对象,并被FastClassInfo对象分别使用f1f2两个属性记录下来,同时使用它们的getIndex(Signature)方法来获取f1f2分别在FastClass对象中的索引。

5.1. FastClass分析

在上面测试代码中,我们指定了CGLIB产生的Class文件的存放目录为/Users/LennonChin/Downloads/Google Driver/Blog/Test/CGLib/,在该目录下生成了6个Class字节码文件:

  • $> tree .
  • .
  • ├── com
  • │   └── coderap
  • │   └── proxy
  • │   └── cglib
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$48029d80.class
  • │   ├── Bugatti$$EnhancerByCGLIB$$4ddb6f26.class
  • │   ├── Bugatti$$FastClassByCGLIB$$e6a580a8.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705$$FastClassByCGLIB$$edb3e882.class
  • │   ├── Ferrari$$EnhancerByCGLIB$$76b91705.class
  • │   └── Ferrari$$FastClassByCGLIB$$9f935905.class
  • └── net
  • └── sf
  • └── cglib
  • ├── core
  • │   └── MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7.class
  • └── proxy
  • └── Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class
  • 9 directories, 8 files

以Bugatti类生成的Class字节码文件为例,其中Bugatti$$FastClassByCGLIB$$e6a580a8.class文件即是目标类Bugatti的FastClass类,而Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$48029d80.class文件则是代理类BugattiEnhancerByCGLIB4ddb6f26的FastClass类;以Bugatti$$FastClassByCGLIB$$e6a580a8.class文件为例,它的反编译内容如下:

  • //
  • // Source code recreated from a .class file by IntelliJ IDEA
  • // (powered by Fernflower decompiler)
  • //
  • package com.coderap.proxy.cglib;
  • import java.lang.reflect.InvocationTargetException;
  • import net.sf.cglib.core.Signature;
  • import net.sf.cglib.reflect.FastClass;
  • public class Bugatti$$FastClassByCGLIB$$e6a580a8 extends FastClass {
  • public Bugatti$$FastClassByCGLIB$$e6a580a8(Class var1) {
  • super(var1);
  • }
  • // 根据方法签名来获取方法在本类中的索引
  • public int getIndex(Signature var1) {
  • String var10000 = var1.toString();
  • switch(var10000.hashCode()) {
  • case -1725733088:
  • if (var10000.equals("getClass()Ljava/lang/Class;")) {
  • return 8;
  • }
  • break;
  • case -1026001249:
  • if (var10000.equals("wait(JI)V")) {
  • return 2;
  • }
  • break;
  • case -919875318:
  • if (var10000.equals("run()V")) {
  • return 0;
  • }
  • break;
  • case -244718353:
  • if (var10000.equals("getInfo()Ljava/lang/String;")) {
  • return 1;
  • }
  • break;
  • case 243996900:
  • if (var10000.equals("wait(J)V")) {
  • return 3;
  • }
  • break;
  • case 946854621:
  • if (var10000.equals("notifyAll()V")) {
  • return 10;
  • }
  • break;
  • case 1116248544:
  • if (var10000.equals("wait()V")) {
  • return 4;
  • }
  • break;
  • case 1826985398:
  • if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
  • return 5;
  • }
  • break;
  • case 1902039948:
  • if (var10000.equals("notify()V")) {
  • return 9;
  • }
  • break;
  • case 1913648695:
  • if (var10000.equals("toString()Ljava/lang/String;")) {
  • return 6;
  • }
  • break;
  • case 1984935277:
  • if (var10000.equals("hashCode()I")) {
  • return 7;
  • }
  • }
  • return -1;
  • }
  • // 根据方法名和方法参数类型数组来获取方法在本类中的索引
  • public int getIndex(String var1, Class[] var2) {
  • switch(var1.hashCode()) {
  • case -1776922004:
  • if (var1.equals("toString")) {
  • switch(var2.length) {
  • case 0:
  • return 6;
  • }
  • }
  • break;
  • case -1295482945:
  • if (var1.equals("equals")) {
  • switch(var2.length) {
  • case 1:
  • if (var2[0].getName().equals("java.lang.Object")) {
  • return 5;
  • }
  • }
  • }
  • break;
  • case -1039689911:
  • if (var1.equals("notify")) {
  • switch(var2.length) {
  • case 0:
  • return 9;
  • }
  • }
  • break;
  • case -75444956:
  • if (var1.equals("getInfo")) {
  • switch(var2.length) {
  • case 0:
  • return 1;
  • }
  • }
  • break;
  • case 113291:
  • if (var1.equals("run")) {
  • switch(var2.length) {
  • case 0:
  • return 0;
  • }
  • }
  • break;
  • case 3641717:
  • if (var1.equals("wait")) {
  • switch(var2.length) {
  • case 0:
  • return 4;
  • case 1:
  • if (var2[0].getName().equals("long")) {
  • return 3;
  • }
  • break;
  • case 2:
  • if (var2[0].getName().equals("long") && var2[1].getName().equals("int")) {
  • return 2;
  • }
  • }
  • }
  • break;
  • case 147696667:
  • if (var1.equals("hashCode")) {
  • switch(var2.length) {
  • case 0:
  • return 7;
  • }
  • }
  • break;
  • case 1902066072:
  • if (var1.equals("notifyAll")) {
  • switch(var2.length) {
  • case 0:
  • return 10;
  • }
  • }
  • break;
  • case 1950568386:
  • if (var1.equals("getClass")) {
  • switch(var2.length) {
  • case 0:
  • return 8;
  • }
  • }
  • }
  • return -1;
  • }
  • // 根据方法名获取方法在本类中的索引
  • public int getIndex(Class[] var1) {
  • switch(var1.length) {
  • case 1:
  • if (var1[0].getName().equals("java.lang.String")) {
  • return 0;
  • }
  • default:
  • return -1;
  • }
  • }
  • // 调用方法
  • public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
  • Bugatti var10000 = (Bugatti)var2;
  • int var10001 = var1;
  • try {
  • switch(var10001) {
  • case 0:
  • var10000.run();
  • return null;
  • case 1:
  • return var10000.getInfo();
  • case 2:
  • var10000.wait(((Number)var3[0]).longValue(), ((Number)var3[1]).intValue());
  • return null;
  • case 3:
  • var10000.wait(((Number)var3[0]).longValue());
  • return null;
  • case 4:
  • var10000.wait();
  • return null;
  • case 5:
  • return new Boolean(var10000.equals(var3[0]));
  • case 6:
  • return var10000.toString();
  • case 7:
  • return new Integer(var10000.hashCode());
  • case 8:
  • return var10000.getClass();
  • case 9:
  • var10000.notify();
  • return null;
  • case 10:
  • var10000.notifyAll();
  • return null;
  • }
  • } catch (Throwable var4) {
  • throw new InvocationTargetException(var4);
  • }
  • throw new IllegalArgumentException("Cannot find matching method/constructor");
  • }
  • public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
  • Bugatti var10000 = new Bugatti;
  • Bugatti var10001 = var10000;
  • int var10002 = var1;
  • try {
  • switch(var10002) {
  • case 0:
  • var10001.<init>((String)var2[0]);
  • return var10000;
  • }
  • } catch (Throwable var3) {
  • throw new InvocationTargetException(var3);
  • }
  • throw new IllegalArgumentException("Cannot find matching method/constructor");
  • }
  • public int getMaxIndex() {
  • return 10;
  • }
  • }

Bugatti$$FastClassByCGLIB$$e6a580a8类中有大量的重载getIndex()方法,根据传入参数的不同,获取方法对应的索引。以getIndex(Signature)方法为例,如果传入的方法是run()方法,则返回0,如果传入的是getInfo()方法,则返回1:

  • // 根据方法签名来获取方法在本类中的索引
  • public int getIndex(Signature var1) {
  • String var10000 = var1.toString();
  • switch(var10000.hashCode()) {
  • ...
  • case -919875318:
  • if (var10000.equals("run()V")) {
  • return 0;
  • }
  • break;
  • case -244718353:
  • if (var10000.equals("getInfo()Ljava/lang/String;")) {
  • return 1;
  • }
  • break;
  • ...
  • return -1;
  • }

相应的在Bugatti$$EnhancerByCGLIB$$4ddb6f26$$FastClassByCGLIB$$48029d80.class文件的getIndex(Signature)方法中,我们看看这两个方法对应的索引:

  • public int getIndex(Signature var1) {
  • String var10000 = var1.toString();
  • switch(var10000.hashCode()) {
  • ...
  • case -919875318:
  • if (var10000.equals("run()V")) {
  • return 0;
  • }
  • break;
  • ...
  • case -244718353:
  • if (var10000.equals("getInfo()Ljava/lang/String;")) {
  • return 21;
  • }
  • break;
  • ...
  • return -1;
  • }

我们在调用MethodProxy的invokeSuper(Object, Object[])方法时其实是调用代理类的FastClass的invoke(int, Object, Object[])方法,其中第一参数传入的是代理类对应方法的索引,第二个参数是调用方法的对象,第三个参数是调用的方法需要的参数:

  • public Object invokeSuper(Object obj, Object[] args) throws Throwable {
  • try {
  • // init操作会处理FastClass相关的配置,在后面会详细介绍
  • init();
  • // 获取FastClassInfo对象fci
  • FastClassInfo fci = fastClassInfo;
  • // 使用fci进行方法调用,f2是代理类的方法,i2是代理类方法的索引,后面会详解
  • return fci.f2.invoke(fci.i2, obj, args);
  • } catch (InvocationTargetException e) {
  • throw e.getTargetException();
  • }
  • }

代理类的FastClass的invoke(int, Object, Object[])方法源码如下:

  • public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
  • 4ddb6f26 var10000 = (4ddb6f26)var2;
  • int var10001 = var1;
  • try {
  • switch(var10001) {
  • case 0:
  • var10000.run();
  • return null;
  • ...
  • case 21:
  • return var10000.getInfo();
  • ...
  • }
  • } catch (Throwable var4) {
  • throw new InvocationTargetException(var4);
  • }
  • throw new IllegalArgumentException("Cannot find matching method/constructor");
  • }

上面代码省去了无关内容,可以发现,其中根据索引0和21分别调用了run()getInfo()方法。

CGLIB采用了FastClass的机制来实现对被拦截方法的调用,对代理的方法在FastClass中进行索引映射,在每次调用时如果存在FastClass时,直接根据索引调用相应的方法会比反射机制快上不少。

5.2. MethodProxy的invoke方法

从MethodProxy的源码可知,它还有一个与invokeSuper(Object, Object[])类似的invoke(Object, Object[])方法,源码如下:

  • public Object invoke(Object obj, Object[] args) throws Throwable {
  • try {
  • init();
  • FastClassInfo fci = fastClassInfo;
  • // 使用fci进行方法调用,f1是目标类的方法,i2是目标类方法的索引
  • return fci.f1.invoke(fci.i1, obj, args);
  • } catch (InvocationTargetException e) {
  • throw e.getTargetException();
  • } catch (IllegalArgumentException e) {
  • if (fastClassInfo.i1 < 0)
  • throw new IllegalArgumentException("Protected method: " + sig1);
  • throw e;
  • }
  • }
  • // invokeSuper方法,用于对比
  • public Object invokeSuper(Object obj, Object[] args) throws Throwable {
  • try {
  • // init操作会处理FastClass相关的配置,在后面会详细介绍
  • init();
  • // 获取FastClassInfo对象fci
  • FastClassInfo fci = fastClassInfo;
  • // 使用fci进行方法调用,f2是代理类的方法,i2是代理类方法的索引,后面会详解
  • return fci.f2.invoke(fci.i2, obj, args);
  • } catch (InvocationTargetException e) {
  • throw e.getTargetException();
  • }
  • }

如果我们在设置的MethodInterceptor拦截器的intercept(...)方法中不使用invokeSuper(...)而使用invoke(...)来进行最终的方法调用会发生什么呢?我们需要观察源码进行分析。

从源码可以,invoke(Object, Object[])方法最大的不同在于,它使用的是fci.f1.invoke(fci.i1, obj, args)进行方法调用,其中f1是目标类的方法,i1是目标类方法的索引;因此我们需要看看前面的Bugatti$$FastClassByCGLIB$$e6a580a8类的invoke(int, Object, Object[])方法:

  • public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
  • Bugatti var10000 = (Bugatti)var2;
  • int var10001 = var1;
  • try {
  • switch(var10001) {
  • case 0:
  • var10000.run();
  • return null;
  • case 1:
  • return var10000.getInfo();
  • ...
  • }
  • } catch (Throwable var4) {
  • throw new InvocationTargetException(var4);
  • }
  • throw new IllegalArgumentException("Cannot find matching method/constructor");
  • }

从源码中可知,此时var2其实是目标类的实例,因此在改方法中其实调用的是目标类实例的run()getInfo()方法,而目标类实例的方法由于经过代理包装,最终又会进入设置的MethodInterceptor拦截器的intercept(...)方法,在该方法中又会调用invoke(...),此时就会进入无线循环引起栈溢出错误。

6. 总结

关于CGLIB的实现原理的讲解已经结束了,这篇文章主要是以Enhancer类进行动态代理时发生的各类操作流程来讲解的,其实CGLIB还有很多其他的高级用法,但底层生成代理类的的原理都是类似的。这里对本文所讲解的内容进行总结。

  1. CGLIB可以为没有实现任何接口的目标类生成代理类,因为它是通过继承目标类的方式来实现动态代理的,但正是由于继承的特性,CGLIB无法为final修饰的类或方法生成代理。
  2. CGLIB底层使用了ASM进行字节码文件的生成和操作。
  3. CGLIB使用了缓存机制对已经生成的代理类进行缓存,减少每次重新生成带来的性能消耗。
  4. CGLIB会使用FastClass机制将代理类中的方法使用索引方式进行标注,减少因反射调用带来的性能消耗。