JVM_cglib技术原理分析

今天我们来分析AOP 技术的核心: 代理。

代理的作用就是在不改变目标方法的情况下,为目标方法添加新功能。

一. 介绍

1.1 静态代理

public interface TI {
    void play();
}

public class T implements TI {
    public void play() {
        System.out.println("I am T");
    }
}

public class TProxy implements TI {
    private TI t;

    public TProxy(TI t) {
        this.t = t;
    }

    @Override
    public void play() {
        long start = System.currentTimeMillis();
        t.play();
        System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
    }
}


public class Test {
    public static void main(String[] args) {
        TI target = new T();
        TI proxy = new TProxy(target);
        proxy.play();
    }
}

运行结果:

I am T
一共花费了:0毫秒

这是一个静态代理的标准写法,分为三个部分:

  • target : 类型是T,目标对象实例。
  • proxy : 类型是TProxy,代理对象实例。
  • TI : 目标对象实例和代理对象实例共同的父接口。

1.2 动态代理

    public static void main(String[] args) {
        TI target = new T();
        TI proxy = (TI) Proxy.newProxyInstance(TI.class.getClassLoader(), 
                new Class[]{TI.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println(String.format("proxy[%s]  method[%s] args[%s]",
                                proxy.getClass().getName(), method.getName(), Arrays.toString(args)));
                        long start = System.currentTimeMillis();
                        method.invoke(target, args);
                        System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
                        return null;
                    }
                });
        proxy.play();
    }

运行结果:

proxy[com.sun.proxy.$Proxy0]  method[play] args[null]
I am T
一共花费了:0毫秒

与静态代理相比较,唯一的区别就是:

  • 静态代理写 TProxy 代理类,然后创建代理类实例proxy,并将目标类实例放入代理类实例proxy中,最后调用代理类实例proxy对应方法。
    *动态代理不用写代理类,而且通过Proxy 创建代理类实例proxy,需要传递一个 InvocationHandler 实例对象,然后通过反射的方式调用目标类实例对应方法。

1.3 cglib代理

    public static void main(String[] args) {
        TI target = new T();

        Enhancer e = new Enhancer();
        e.setSuperclass(T.class);
        e.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects,
                                    MethodProxy methodProxy) throws Throwable {
                long start = System.currentTimeMillis();
                methodProxy.invoke(target, objects);
                System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
                return null;
            }
        });
        T proxy = (T) e.create();
        
        proxy.play();
    }

运行结果

I am T
一共花费了:17毫秒

与静态代理相比较,看起来比较复杂,它需要通过Enhancer 创建代理实例proxy,然后调用代理方法。但是这里比较神奇的是代理类居然是 T 的子类,这些我们下面分析。

二. 动态代理原理

2.1 newProxyInstance 方法

首先分析一下 Proxy.newProxyInstance(...) 方法:

  public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

这个方法流程主要分成三步:

  • 检查一下传入的参数。
  • 通过 getProxyClass0(loader, intfs) 方法查找或者生成代理类的 Class
  • 获取代理类的构造方法,创建代理类实例。

2.2 getProxyClass0 方法

那么重点就是这个 getProxyClass0(loader, intfs) 方法了。

    private static final WeakCache[], Class>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    private static Class getProxyClass0(ClassLoader loader,
                                           Class... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

getProxyClass0(loader, intfs) 方法主要就是从 proxyClassCache 缓存中查找或者生成代理类的 Class

WeakCache 有三个泛型变量:

  • K : 缓存的key 的类型。
  • P : 缓存参数类型。
  • V : 缓存的value 的类型。
    private static final WeakCache[], Class>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

因此 proxyClassCache 缓存实例的key 是类加载器ClassLoader,参数是类数组Class[],缓存的值是Class 实例。

  • KeyFactory 是用Key值和参数值来创建缓存中唯一的键的值。
  • ProxyClassFactory 是用来生成缓存值的实例。

2.3 KeyFactory

  private static final class KeyFactory
        implements BiFunction[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class[] interfaces) {
            switch (interfaces.length) {
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }

根据代理的接口数组interfaces 生成不同的缓存中key 值。

private static final class Key1 extends WeakReference> {
        private final int hash;

        Key1(Class intf) {
            super(intf);
            this.hash = intf.hashCode();
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            Class intf;
            return this == obj ||
                   obj != null &&
                   obj.getClass() == Key1.class &&
                   (intf = get()) != null &&
                   intf == ((Key1) obj).get();
        }
    }

2.4 ProxyClassFactory

    private static final class ProxyClassFactory
        implements BiFunction[], Class>
    {
        // prefix for all proxy class names
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class apply(ClassLoader loader, Class[] interfaces) 
       { .... }
}

这个就是代理类的生成器,有两个静态变量:

  • proxyClassNamePrefix : 所有代理类名的前缀。
  • nextUniqueNumber : 下一个用于生成唯一代理类名的数字。

重点分析 apply 方法

  @Override
  public Class apply(ClassLoader loader, Class[] interfaces) {
        Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        for (Class intf : interfaces) {
            /*
             * Verify that the class loader resolves the name of this
             * interface to the same Class object.
             */
            Class interfaceClass = null;
            try {
                interfaceClass = Class.forName(intf.getName(), false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != intf) {
                throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
            }
            /*
             * Verify that the Class object actually represents an
             * interface.
             */
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
            }
            /*
             * Verify that this interface is not a duplicate.
             */
            if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
            }
        }
     ......
 }

首先需要检查参数,接口数组 interfaces 的类加载器是不是就是 loader,接口数组 interfaces是不是都是接口类型,接口数组 interfaces有没有重复的接口。

 @Override
 public Class apply(ClassLoader loader, Class[] interfaces) {
     ......
        String proxyPkg = null;     // package to define proxy class in
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

        /*
         * Record the package of a non-public proxy interface so that the
         * proxy class will be defined in the same package.  Verify that
         * all non-public proxy interfaces are in the same package.
         */
        for (Class intf : interfaces) {
            int flags = intf.getModifiers();
            if (!Modifier.isPublic(flags)) {
                accessFlags = Modifier.FINAL;
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                }
            }
        }

        if (proxyPkg == null) {
            // if no non-public proxy interfaces, use com.sun.proxy package
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }

        /*
         * Choose a name for the proxy class to generate.
         */
        long num = nextUniqueNumber.getAndIncrement();
        String proxyName = proxyPkg + proxyClassNamePrefix + num;
     ......
 }

验证接口数组 interfaces 类的访问权限,以及生成代理类名字 proxyName

 @Override
 public Class apply(ClassLoader loader, Class[] interfaces) {
        /*
         * Generate the specified proxy class.
         */
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
        try {
            return defineClass0(loader, proxyName,
                    proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            /*
             * A ClassFormatError here means that (barring bugs in the
             * proxy class generation code) there was some other
             * invalid aspect of the arguments supplied to the proxy
             * class creation (such as virtual machine limitations
             * exceeded).
             */
            throw new IllegalArgumentException(e.toString());
        }
     ......
 }

通过 ProxyGenerator.generateProxyClass(...) 方法生成代理类,并通过类加载器 loader 加载它。

2.5 ProxyGenerator

    public static byte[] generateProxyClass(final String name,
                                            Class[] interfaces,
                                            int accessFlags)
    {
        ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
        final byte[] classFile = gen.generateClassFile();

        if (saveGeneratedFiles) {
            java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction() {
                public Void run() {
                    try {
                        int i = name.lastIndexOf('.');
                        Path path;
                        if (i > 0) {
                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
                            Files.createDirectories(dir);
                            path = dir.resolve(name.substring(i+1, name.length()) + ".class");
                        } else {
                            path = Paths.get(name + ".class");
                        }
                        Files.write(path, classFile);
                        return null;
                    } catch (IOException e) {
                        throw new InternalError(
                            "I/O exception saving generated file: " + e);
                    }
                }
            });
        }

        return classFile;
    }

这个方法流程比较简单:

  • 创建 ProxyGenerator 实例。
  • 通过 gen.generateClassFile() 方法生成代理类。
  • 如果 saveGeneratedFilestrue,那么就将代理类写到本地文件中。

饶了一大圈,终于找到了生成代理类的实现方法了,下面我们就分析一下gen.generateClassFile()方法。

    private byte[] generateClassFile() {
        addProxyMethod(hashCodeMethod, Object.class);
        addProxyMethod(equalsMethod, Object.class);
        addProxyMethod(toStringMethod, Object.class);
        ......
    }

Object 类的 hash,equalstoString 方法添加到代理类的方法集合proxyMethods

    private byte[] generateClassFile() {
        ......
        for (Class intf : interfaces) {
            for (Method m : intf.getMethods()) {
                addProxyMethod(m, intf);
            }
        }
        ......
    }

遍历接口数组interfaces,将接口中的方法都添加到代理类的方法集合proxyMethods

    private byte[] generateClassFile() {
        ......
       for (List sigmethods : proxyMethods.values()) {
            checkReturnTypes(sigmethods);
        }
        ......
    }

检查一下方法集合 proxyMethods 中具有相同签名的方法列表返回值类型。

    private byte[] generateClassFile() {
        ......
        try {
            methods.add(generateConstructor());

            for (List sigmethods : proxyMethods.values()) {
                for (ProxyMethod pm : sigmethods) {

                    // add static field for method's Method object
                    fields.add(new FieldInfo(pm.methodFieldName,
                        "Ljava/lang/reflect/Method;",
                         ACC_PRIVATE | ACC_STATIC));

                    // generate code for proxy method and add it
                    methods.add(pm.generateMethod());
                }
            }

            methods.add(generateStaticInitializer());

        } catch (IOException e) {
            throw new InternalError("unexpected I/O Exception", e);
        }

        if (methods.size() > 65535) {
            throw new IllegalArgumentException("method limit exceeded");
        }
        if (fields.size() > 65535) {
            throw new IllegalArgumentException("field limit exceeded");
        }
        ......
    }

生成代理类中所有字段fields和方法methods

代理类中每一个方法,都会有一个对应的 java/lang/reflect/Method 类型的字段。

    private byte[] generateClassFile() {
        ......
 cp.getClass(dotToSlash(className));
        cp.getClass(superclassName);
        for (Class intf: interfaces) {
            cp.getClass(dotToSlash(intf.getName()));
        }

        /*
         * Disallow new constant pool additions beyond this point, since
         * we are about to write the final constant pool table.
         */
        cp.setReadOnly();

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(bout);

        try {
            /*
             * Write all the items of the "ClassFile" structure.
             * See JVMS section 4.1.
             */
                                        // u4 magic;
            dout.writeInt(0xCAFEBABE);
                                        // u2 minor_version;
            dout.writeShort(CLASSFILE_MINOR_VERSION);
                                        // u2 major_version;
            dout.writeShort(CLASSFILE_MAJOR_VERSION);

            cp.write(dout);             // (write constant pool)
            ......
        }
       return bout.toByteArray();
    }

开始生成代理类的字节码数据。

2.6 示例

以我们之前例子代码

    public static void main(String[] args) {
        TI target = new T();
        TI proxy = (TI) Proxy.newProxyInstance(TI.class.getClassLoader(), 
                new Class[]{TI.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println(String.format("proxy[%s]  method[%s] args[%s]",
                                proxy.getClass().getName(), method.getName(), Arrays.toString(args)));
                        long start = System.currentTimeMillis();
                        method.invoke(target, args);
                        System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
                        return null;
                    }
                });
        proxy.play();
    }

生成的代理类如下:

package com.sun.proxy;

import com.zhang.bytecode.proxy.TI;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements TI {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void play() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.zhang.bytecode.proxy.TI").getMethod("play");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

我们观察到如下特点:

  • 代理类继承自Proxy 类,实现了我们传递的代理接口 TI,类名就叫 $Proxy0
  • 代理类有四个静态字段,分别对应代理类的四个方法 equals,hashCode,toStringplay

    这些静态字段,通过静态代码块中赋值,类型都是 Method,用于反射调用目标方法。

  • 代理类有四个方法,它们都是调用 InvocationHandler 实例的 invoke 方法,传递代理类实例this,对应的代理方法 Method 和方法参数 agrs

2.7 小结

动态代理实现原理我们已经清楚了,那么它的缺点也是显而易见的,主要是两点:

  • 只能代理接口,这个是由动态代理生成代理类的原理决定的,只能生成实现接口的代理类。
  • 通过反射调用目标方法,必定会影响效率。

2.8 注解的实现

2.8.1 注解是类还是接口

大家有没有想过,我们使用注解是类还是接口呢。
我们简单写一个注解类:

public @interface TA {
    int age() default 10;
    String name();
}

通过javap -v -p TA.class 命令查看字节码内容:

 Last modified 2021-12-26; size 241 bytes
  MD5 checksum 93aee1f6a305f95e0e48b05bdf959a51
  Compiled from "TA.java"
public interface com.zhang.bytecode.proxy.TA extends java.lang.annotation.Annotation
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
Constant pool:
   #1 = Class              #12            // com/zhang/bytecode/proxy/TA
   #2 = Class              #13            // java/lang/Object
   #3 = Class              #14            // java/lang/annotation/Annotation
   #4 = Utf8               age
   #5 = Utf8               ()I
   #6 = Utf8               AnnotationDefault
   #7 = Integer            10
   #8 = Utf8               name
   #9 = Utf8               ()Ljava/lang/String;
  #10 = Utf8               SourceFile
  #11 = Utf8               TA.java
  #12 = Utf8               com/zhang/bytecode/proxy/TA
  #13 = Utf8               java/lang/Object
  #14 = Utf8               java/lang/annotation/Annotation
{
  public abstract int age();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_ABSTRACT
    AnnotationDefault:
      default_value: I#7
  public abstract java.lang.String name();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "TA.java"

通过 public interface com.zhang.bytecode.proxy.TA extends java.lang.annotation.Annotation ;我们知道注解 TA 是一个接口,而且是 Annotation 的子接口。

2.8.2 注解实例

那我们就有疑惑,我们怎么获取到注解实例的呢?
例如:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface TA {
    int age() default 10;
    String name();
}

public class T {
    @TA(name = "zhang")
    public String field;
}

    public static void main(String[] args) throws Exception {
        Field field = T.class.getDeclaredField("field");
        TA ta = field.getAnnotation(TA.class);
        System.out.println(String.format("TA age[%s]  name[%s]  class[%s]",
                ta.age(), ta.name(), ta.getClass()));
    }

运行结果就是

TA age[10]  name[zhang]  class[class com.sun.proxy.$Proxy1]

很明显我们获取了注解 TA 的实例,这个实例的类名是 class com.sun.proxy.$Proxy1,这一眼就知道了,它是一个动态代理类名。

2.8.3 getAnnotation 方法

   public  T getAnnotation(Class annotationClass) {
        Objects.requireNonNull(annotationClass);
        return annotationClass.cast(declaredAnnotations().get(annotationClass));
    }

 private Map, Annotation> declaredAnnotations() {
        Map, Annotation> declAnnos;
        if ((declAnnos = declaredAnnotations) == null) {
            synchronized (this) {
                if ((declAnnos = declaredAnnotations) == null) {
                    Field root = this.root;
                    if (root != null) {
                        declAnnos = root.declaredAnnotations();
                    } else {
                        declAnnos = AnnotationParser.parseAnnotations(
                                annotations,
                                sun.misc.SharedSecrets.getJavaLangAccess()
                                        .getConstantPool(getDeclaringClass()),
                                getDeclaringClass());
                    }
                    declaredAnnotations = declAnnos;
                }
            }
        }
        return declAnnos;
    }

主要还是看 AnnotationParser.parseAnnotations(...) 方法获取注解实例。

2.8.4 AnnotationParser.parseAnnotations(...) 方法

    public static Map, Annotation> parseAnnotations(
                byte[] rawAnnotations,
                ConstantPool constPool,
                Class container) {
        if (rawAnnotations == null)
            return Collections.emptyMap();

        try {
            return parseAnnotations2(rawAnnotations, constPool, container, null);
        } catch(BufferUnderflowException e) {
            throw new AnnotationFormatError("Unexpected end of annotations.");
        } catch(IllegalArgumentException e) {
            // Type mismatch in constant pool
            throw new AnnotationFormatError(e);
        }
    }

调用 parseAnnotations2(...) 方法生成注解实例。

  private static Map, Annotation> parseAnnotations2(
                byte[] rawAnnotations,
                ConstantPool constPool,
                Class container,
                Class[] selectAnnotationClasses) {
        Map, Annotation> result =
            new LinkedHashMap, Annotation>();
        ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
        int numAnnotations = buf.getShort() & 0xFFFF;
        for (int i = 0; i < numAnnotations; i++) {
            Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
            if (a != null) {
                Class klass = a.annotationType();
                if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
                    result.put(klass, a) != null) {
                        throw new AnnotationFormatError(
                            "Duplicate annotation for class: "+klass+": " + a);
            }
        }
        }
        return result;
    }

通过 parseAnnotation2(...) 方法生成单个注解实例。

   private static Annotation parseAnnotation2(ByteBuffer buf,
                                              ConstantPool constPool,
                                              Class container,
                                              boolean exceptionOnMissingAnnotationClass,
                                              Class[] selectAnnotationClasses) {
        int typeIndex = buf.getShort() & 0xFFFF;
        Class annotationClass = null;
        String sig = "[unknown]";
        try {
            try {
                sig = constPool.getUTF8At(typeIndex);
                annotationClass = (Class)parseSig(sig, container);
            } catch (IllegalArgumentException ex) {
                // support obsolete early jsr175 format class files
                annotationClass = (Class)constPool.getClassAt(typeIndex);
            }
        } catch (NoClassDefFoundError e) {
            if (exceptionOnMissingAnnotationClass)
                // note: at this point sig is "[unknown]" or VM-style
                // name instead of a binary name
                throw new TypeNotPresentException(sig, e);
            skipAnnotation(buf, false);
            return null;
        }
        catch (TypeNotPresentException e) {
            if (exceptionOnMissingAnnotationClass)
                throw e;
            skipAnnotation(buf, false);
            return null;
        }
        if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
            skipAnnotation(buf, false);
            return null;
        }
        AnnotationType type = null;
        try {
            type = AnnotationType.getInstance(annotationClass);
        } catch (IllegalArgumentException e) {
            skipAnnotation(buf, false);
            return null;
        }

        Map> memberTypes = type.memberTypes();
        Map memberValues =
            new LinkedHashMap(type.memberDefaults());

        int numMembers = buf.getShort() & 0xFFFF;
        for (int i = 0; i < numMembers; i++) {
            int memberNameIndex = buf.getShort() & 0xFFFF;
            String memberName = constPool.getUTF8At(memberNameIndex);
            Class memberType = memberTypes.get(memberName);

            if (memberType == null) {
                // Member is no longer present in annotation type; ignore it
                skipMemberValue(buf);
            } else {
                Object value = parseMemberValue(memberType, buf, constPool, container);
                if (value instanceof AnnotationTypeMismatchExceptionProxy)
                    ((AnnotationTypeMismatchExceptionProxy) value).
                        setMember(type.members().get(memberName));
                memberValues.put(memberName, value);
            }
        }
        return annotationForMap(annotationClass, memberValues);
    }

方法流程:

  • 先获取注解的 Class 对象annotationClass
  • 通过 annotationClass 获取 AnnotationType 类型实例type,里面包含着注解类所有方法,方法默认返回值和设置的方法返回值。

    例如 @TA(name = "zhang") ,这个注解的方法有两个 age()name(), 对应的值是 10zhang

  • 通过 AnnotationType 类型实例type构建集合 memberValues,包含这个注解的所有方法和对应的返回值。
  • 通过 annotationForMap(annotationClass, memberValues) 方法生成注解实例。
    public static Annotation annotationForMap(final Class type,
                                              final Map memberValues)
    {
        return AccessController.doPrivileged(new PrivilegedAction() {
            public Annotation run() {
                return (Annotation) Proxy.newProxyInstance(
                    type.getClassLoader(), new Class[] { type },
                    new AnnotationInvocationHandler(type, memberValues));
            }});
    }

通过 Proxy 生成注解的动态代理实例,传递一个 AnnotationInvocationHandler 对象。

2.8.5 AnnotationInvocationHandler

    public Object invoke(Object proxy, Method method, Object[] args) {
        String member = method.getName();
        Class[] paramTypes = method.getParameterTypes();

        // Handle Object and Annotation methods
        if (member.equals("equals") && paramTypes.length == 1 &&
            paramTypes[0] == Object.class)
            return equalsImpl(args[0]);
        if (paramTypes.length != 0)
            throw new AssertionError("Too many parameters for an annotation method");

        switch(member) {
        case "toString":
            return toStringImpl();
        case "hashCode":
            return hashCodeImpl();
        case "annotationType":
            return type;
        }

        // Handle annotation member accessors
        Object result = memberValues.get(member);

        if (result == null)
            throw new IncompleteAnnotationException(type, member);

        if (result instanceof ExceptionProxy)
            throw ((ExceptionProxy) result).generateException();

        if (result.getClass().isArray() && Array.getLength(result) != 0)
            result = cloneArray(result);

        return result;
    }

你会发现调用注解代理类实例注解方法的时候,会通过方法名直接从 memberValues 中获取结果值。

三. cglib代理原理

3.1 ClassGenerator

import org.objectweb.asm.ClassVisitor;

public interface ClassGenerator {
    void generateClass(ClassVisitor v) throws Exception;
}

cglib 所有类生成器的接口,只有一个方法generateClass(ClassVisitor v),通过 ASMClassVisitor 实例来生成类。

3.2 AbstractClassGenerator

所有cglib类生成器的抽象基类,提供了缓存功能缓存生成的字节码文件来提高效率,还提供了各种各样的构造,让使用者定制类加载器 ClassLoader,生成的类的名称以及在生成之前应用的转换。

3.2.1 重要属性

    private static volatile Map CACHE = new WeakHashMap();

    private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;

CACHE 缓存类加载器ClassLoader 生成的所有代理类数据ClassLoaderData
strategy 是代理类的生成策略。

3.2.2 create(Object key) 方法

  protected Object create(Object key) {
        try {
            ClassLoader loader = getClassLoader();
            Map cache = CACHE;
            ClassLoaderData data = cache.get(loader);
            if (data == null) {
                synchronized (AbstractClassGenerator.class) {
                    cache = CACHE;
                    data = cache.get(loader);
                    if (data == null) {
                        Map newCache = new WeakHashMap(cache);
                        data = new ClassLoaderData(loader);
                        newCache.put(loader, data);
                        CACHE = newCache;
                    }
                }
            }
            this.key = key;
            Object obj = data.get(this, getUseCache());
            if (obj instanceof Class) {
                return firstInstance((Class) obj);
            }
            return nextInstance(obj);
        } catch (RuntimeException e) {
            throw e;
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

方法流程主要分为两步:

  • 根据类加载器ClassLoader 从缓存CACHE 获取对应的 ClassLoaderData 实例。

    如果没有对应的ClassLoaderData 实例,那么就创建它,并放到缓存中。

  • 通过ClassLoaderData 实例的 data.get(this, getUseCache()) 获取代理类Class或者代理类实例。

3.2.3 ClassLoaderData

   private final LoadingCache generatedClasses;
   private final WeakReference classLoader;
   private static final Function GET_KEY = new Function() {
            public Object apply(AbstractClassGenerator gen) {
                return gen.key;
            }
        };

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

构造方法流程:

  • 使用弱引用 WeakReference 类型的 classLoader 保存传进来的类加载器。
  • 创建缓存generatedClasses 值的生成器load

    通过类生成器 AbstractClassGeneratorgen.generate(ClassLoaderData.this) 方法生成代理类Class

  • 缓存generatedClasses 键的生成器GET_KEY

    就是返回类生成器 AbstractClassGenerator 的成员变量gen.key,在create(Object key) 方法中赋值。

  • 最后创建LoadingCache 类型缓存实例 generatedClasses

    缓存generatedClasses作用就是存储类生成器 AbstractClassGenerator 所有生成的代理类Class

     public Object get(AbstractClassGenerator gen, boolean useCache) {
            if (!useCache) {
              return gen.generate(ClassLoaderData.this);
            } else {
              Object cachedValue = generatedClasses.get(gen);
              return gen.unwrapCachedValue(cachedValue);
            }
        }
  • 如果不使用缓存,那么就通过类生成器 AbstractClassGeneratorgen.generate(ClassLoaderData.this) 方法生成代理类Class
  • 如果使用缓存,那么就从缓存generatedClasses 中查找,如果存在那么就返回,不存在就通过缓存值的生成器load创建。

3.2.4 generate(ClassLoaderData data) 方法

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

方法流程:

  • 先判断类加载器classLoader 是否还存在,不存在就直接报错。
  • 通过 generateClassName(...) 方法生成代理类的名字。
  • 如果 attemptLoadtrue,尝试通过类名从类加载器classLoader 中加载代理类Class,如果有就直接返回了。
  • 通过 strategy.generate(this) 生成代理类的字节数据。
  • 最后将生成的代理类字节数据通过类加载器classLoader 加载。

3.2.5 DefaultGeneratorStrategy

public class DefaultGeneratorStrategy implements GeneratorStrategy {
    public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
    
    public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = getClassVisitor();
        transform(cg).generateClass(cw);
        return transform(cw.toByteArray());
    }

    protected DebuggingClassWriter getClassVisitor() throws Exception {
      return new DebuggingClassWriter(ClassWriter.COMPUTE_FRAMES);
    }

    protected final ClassWriter getClassWriter() {
    // Cause compile / runtime errors for people who implemented the old
    // interface without using @Override
    throw new UnsupportedOperationException("You are calling " +
        "getClassWriter, which no longer exists in this cglib version.");
    }
    
    protected byte[] transform(byte[] b) throws Exception {
        return b;
    }

    protected ClassGenerator transform(ClassGenerator cg) throws Exception {
        return cg;
    }
}

GeneratorStrategy 默认实现类DefaultGeneratorStrategy 非常简单,就是创建 DebuggingClassWriter 实例来接收类生成器实例cg 传递的数据,生成代理类字节码文件。

3.3 KeyFactory

先介绍KeyFactory 类的功能,在cglib 中经常用到它,它的主要功能就是生成特定接口实例。

不要惊讶,它肯定是生成了接口的实现代理类,然后创建这个代理类的实例赋值给接口实例。

3.3.1 静态创建方法

 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(Class keyInterface, KeyFactoryCustomizer first, List next) {
        return create(keyInterface.getClassLoader(), keyInterface, first, next);
    }

    public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
        return create(loader, keyInterface, customizer, Collections.emptyList());
    }

    public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer,
                                    List next) {
        Generator gen = new Generator();
        gen.setInterface(keyInterface);

        if (customizer != null) {
            gen.addCustomizer(customizer);
        }
        if (next != null && !next.isEmpty()) {
            for (KeyFactoryCustomizer keyFactoryCustomizer : next) {
                gen.addCustomizer(keyFactoryCustomizer);
            }
        }
        gen.setClassLoader(loader);
        return gen.create();
    }

传递一个接口的Class 对象,然后创建 KeyFactory.Generator 类生成器实例,最后通过类生成器生成 KeyFactory 实例并返回。

3.3.2 KeyFactory.Generator

KeyFactory.Generator 继承自 AbstractClassGenerator 类。

       public KeyFactory create() {
            setNamePrefix(keyInterface.getName());
            return (KeyFactory)super.create(keyInterface.getName());
        }

使用接口名当生成接口代理类的唯一键。

下面就是重点分析 generateClass(ClassVisitor v)` 方法了

    public void generateClass(ClassVisitor v) {
        ClassEmitter ce = new ClassEmitter(v);

        Method newInstance = ReflectUtils.findNewInstance(keyInterface);
        if (!newInstance.getReturnType().equals(Object.class)) {
            throw new IllegalArgumentException("newInstance method must return Object");
        }
        .......
    }

通过ClassVisitor 实例创建 ClassEmitter 对象,ClassEmittercglib 提供的工具类,更方便生成字节码数据。
接口必须有 newInstance 方法,而且返回值必须是 Object 类型。

    public void generateClass(ClassVisitor v) {
        .......
        Type[] parameterTypes = 
        TypeUtils.getTypes(newInstance.getParameterTypes());
            ce.begin_class(Constants.V1_8,
                           Constants.ACC_PUBLIC,
                           getClassName(),
                           KEY_FACTORY,
                           new Type[]{ Type.getType(keyInterface) },
                           Constants.SOURCE_FILE);
            EmitUtils.null_constructor(ce);
            EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
        .......
    }

通过 ClassEmitter 对象生成空参构造方法和接口类的方法等等。

3.3.3 示例

public class KeySample {
    private interface MyFactory {
        public Object newInstance(int a, char[] b, String d);
    }
    public static void main(String[] args) {
        MyFactory f = (MyFactory)KeyFactory.create(MyFactory.class);
        Object key1 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
        Object key2 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
        Object key3 = f.newInstance(20, new char[]{ 'a', '_' }, "hello");
        System.out.println(key1.equals(key2));
        System.out.println(key2.equals(key3));
    }
}

运行结果如下:

true
false

生成代理类如下:

public class KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627 extends KeyFactory implements MyFactory {
    private final int FIELD_0;
    private final char[] FIELD_1;
    private final String FIELD_2;

    public KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627() {
    }

    public Object newInstance(int var1, char[] var2, String var3) {
        return new KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627(var1, var2, var3);
    }

    public KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627(int var1, char[] var2, String var3) {
        this.FIELD_0 = var1;
        this.FIELD_1 = var2;
        this.FIELD_2 = var3;
    }

    public int hashCode() {
        int var10000 = 179 * 467063 + this.FIELD_0;
        char[] var10001 = this.FIELD_1;
        if (var10001 != null) {
            char[] var1 = var10001;

            for(int var2 = 0; var2 < var1.length; ++var2) {
                var10000 = var10000 * 467063 + var1[var2];
            }
        }

        int var10002 = var10000 * 467063;
        String var3 = this.FIELD_2;
        return var10002 + (var3 != null ? var3.hashCode() : 0);
    }

    public boolean equals(Object var1) {
        if (var1 instanceof KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627 && this.FIELD_0 == ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_0) {
            char[] var10000 = this.FIELD_1;
            char[] var10001 = ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_1;
            if (var10001 == null) {
                if (var10000 != null) {
                    return false;
                }
            } else {
                label71: {
                    if (var10000 != null) {
                        if (var10001.length == var10000.length) {
                            char[] var2 = var10001;
                            char[] var3 = var10000;
                            int var4 = 0;

                            while(true) {
                                if (var4 >= var2.length) {
                                    break label71;
                                }

                                if (var2[var4] != var3[var4]) {
                                    return false;
                                }

                                ++var4;
                            }
                        }
                    }

                    return false;
                }
            }

            String var5 = this.FIELD_2;
            String var6 = ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_2;
            if (var6 == null) {
                if (var5 == null) {
                    return true;
                }
            } else if (var5 != null && var5.equals(var6)) {
                return true;
            }
        }

        return false;
    }

    public String toString() {
        StringBuffer var10000 = (new StringBuffer()).append(this.FIELD_0).append(", ");
        char[] var10001 = this.FIELD_1;
        if (var10001 != null) {
            var10000 = var10000.append("{");
            char[] var1 = var10001;

            for(int var2 = 0; var2 < var1.length; ++var2) {
                var10000 = var10000.append(var1[var2]).append(", ");
            }

            var10000.setLength(var10000.length() - 2);
            var10000 = var10000.append("}");
        } else {
            var10000 = var10000.append("null");
        }

        var10000 = var10000.append(", ");
        String var5 = this.FIELD_2;
        return (var5 != null ? var10000.append(var5.toString()) : var10000.append("null")).toString();
    }
}

我们发现这个代理类有如下特点:

  • 居然继承自KeyFactory 类,实现了传递的 MyFactory 接口。
  • 实现 newInstance 方法,返回当前代理类的实例,也是 MyFactory 接口的实例。
  • 复写了 hashCodeequals 方法,保证了如果参数相同,那么两个实例就是相同的。

KeyFactory 的作用就是创建Key 值,生成代理类已经帮我们实现了 hashCodeequals 相等方法,而且它没有使用反射创建实例,速度还是非常快的。

3.4 Enhancer

3.4.1 create 方法

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

   private Object createHelper() {
        preValidate();
        Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
                ReflectUtils.getNames(interfaces),
                filter == ALL_ZERO ? null : new WeakCacheKey(filter),
                callbackTypes,
                useFactory,
                interceptDuringConstruction,
                serialVersionUID);
        this.currentKey = key;
        Object result = super.create(key);
        return result;
    }

主要就两个步骤:

  • 通过 KEY_FACTORY 获取要生成代理类的唯一 Key 值。
  • 调用 AbstractClassGeneratorcreate(Object key) 获取代理类实例。
    private static final EnhancerKey KEY_FACTORY =
      (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);

    public interface EnhancerKey {
        public Object newInstance(String type,
                                  String[] interfaces,
                                  WeakCacheKey filter,
                                  Type[] callbackTypes,
                                  boolean useFactory,
                                  boolean interceptDuringConstruction,
                                  Long serialVersionUID);
    }

可以看出 Enhancer 生成的代理类需要的唯一 Key 值,一共包含7 个参数。

3.4.2 generateClass(ClassVisitor v) 方法

    public void generateClass(ClassVisitor v) throws Exception {
        Class sc = (superclass == null) ? Object.class : superclass;

        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);
        .......
    }
  • superclass 有值,表示代理类; superclass 没有值,那么只是代理接口。
  • 代理类的父类superclass 访问标志不能是 final 的。
  • 获取父类superclass的构造函数。
    public void generateClass(ClassVisitor v) throws Exception {
        .......
        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);
            }
        });
        .......
    }
  • 通过 getMethods(...) 得到代理类应该有的所有方法。
  • 通过 Transformer() 将方法转成 MethodInfo 对象。
    public void generateClass(ClassVisitor v) throws Exception {
        .......
        ClassEmitter e = new ClassEmitter(v);
        if (currentData == null) {
        e.begin_class(Constants.V1_8,
                      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_8,
                    Constants.ACC_PUBLIC,
                    getClassName(),
                    null,
                    new Type[]{FACTORY},
                    Constants.SOURCE_FILE);
        }
        List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
        .......
    }

通过 ClassEmitter 实例创建代理类的字节码文件数据。

3.4.3 示例

public class Test {
    public static void main(String[] args) {
        final TI target = new T();

        Enhancer e = new Enhancer();
        e.setSuperclass(T.class);
        e.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects,
                                    MethodProxy methodProxy) throws Throwable {
                long start = System.currentTimeMillis();
//                methodProxy.invoke(target, objects);
                System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
                return null;
            }
        });
        T proxy = (T) e.create();

        proxy.play();
    }
}

注意这里将 methodProxy.invoke(target, objects); 这行注释了,这个后面再说。

会生成三个代理类文件:

  • EnhancerKey 的代理类

     public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72 extends KeyFactory implements EnhancerKey {
    
       private final String FIELD_0;
       private final String[] FIELD_1;
       private final WeakCacheKey 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, WeakCacheKey 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, WeakCacheKey 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() { ...... }
        public int equals(Object var1) { ...... }
        public int toString() { ...... }
    

    这个是EnhancerKEY_FACTORY 字段生成的。

  • MethodWrapperKey 的代理类

    public class MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7 extends KeyFactory implements MethodWrapperKey {
       private final String FIELD_0;
       private final String[] FIELD_1;
       private final String FIELD_2;
    
       public MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7() {
       }
    
       public Object newInstance(String var1, String[] var2, String var3) {
           return new MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(var1, var2, var3);
     }
    
       public MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(String var1, String[] var2, String var3) {
           this.FIELD_0 = var1;
           this.FIELD_1 = var2;
           this.FIELD_2 = var3;
       }
        public int hashCode() { ...... }
        public int equals(Object var1) { ...... }
        public int toString() { ...... }
    

    这个是 MethodWrapper 类中的 KEY_FACTORY 生成的。在Enhancer类的generateClass(ClassVisitor v) 方法中会调用到 MethodWrapper.create(method) 方法。

  • 目标类的代理类

     public class T$$EnhancerByCGLIB$$422fccc9 extends T implements Factory {
         private boolean CGLIB$BOUND;
       public static Object CGLIB$FACTORY_DATA;
       private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
       private static final Callback[] CGLIB$STATIC_CALLBACKS;
       private MethodInterceptor CGLIB$CALLBACK_0;
       private static Object CGLIB$CALLBACK_FILTER;
       private static final Method CGLIB$play$0$Method;
       private static final MethodProxy CGLIB$play$0$Proxy;
       private static final Object[] CGLIB$emptyArgs;
       private static final Method CGLIB$equals$1$Method;
       private static final MethodProxy CGLIB$equals$1$Proxy;
       private static final Method CGLIB$toString$2$Method;
       private static final MethodProxy CGLIB$toString$2$Proxy;
       private static final Method CGLIB$hashCode$3$Method;
       private static final MethodProxy CGLIB$hashCode$3$Proxy;
       private static final Method CGLIB$clone$4$Method;
       private static final MethodProxy CGLIB$clone$4$Proxy;
    }
        public final void play() {
           MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
           if (var10000 == null) {
               CGLIB$BIND_CALLBACKS(this);
               var10000 = this.CGLIB$CALLBACK_0;
           }
    
           if (var10000 != null) {
               var10000.intercept(this, CGLIB$play$0$Method, CGLIB$emptyArgs, CGLIB$play$0$Proxy);
           } else {
               super.play();
           }
     }
    
    • 代理类继承自目标类,而且实现了 Factory 接口。
    • 可以看到 play() 方法,会调用MethodInterceptor 实例的intercept方法。

如果我们调用 methodProxy.invoke(target, objects); 方法,会发现又生成两个代理类,这个就是我们接下来就讲解的MethodProxy 类。

3.5 MethodProxy

3.5.1 invoke 方法

    public Object invoke(Object obj, Object[] args) throws Throwable {
        try {
            init();
            FastClassInfo fci = fastClassInfo;
            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;
        }
    }
  • 先调用 init() 进行初始化。
  • 然后调用 fci.f1.invoke(fci.i1, obj, args) 调用目标方法。

3.5.2 init() 方法

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

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

    private static class FastClassInfo
    {
        FastClass f1;
        FastClass f2;
        int i1;
        int i2;
    }

fastClassInfo 没有值的时候,就会创建它;fastClassInfo 中有四个属性:

  • f1i1 : 代表目标类实例对应快速调用类 FastClass
  • f2i2 : 代表代理类实例对应快速调用类 FastClass

3.5.3 helper(...) 方法

    private static FastClass helper(CreateInfo ci, Class type) {
        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);
        return g.create();
    }

就是通过 FastClass.Generator 类生成器生成 FastClass 代理类。

3.5.4 FastClass.Generator

        public FastClass create() {
            setNamePrefix(type.getName());
            return (FastClass)super.create(type.getName());
        }

通过 AbstractClassGeneratorcreate 方法生成代理类。

        public void generateClass(ClassVisitor v) throws Exception {
            new FastClassEmitter(v, getClassName(), type);
        }

主要靠 FastClassEmitter 类来生成字节码文件。

3.5.5 FastClassEmitter

   public FastClassEmitter(ClassVisitor v, String className, Class type) {
        super(v);

        Type base = Type.getType(type);
        begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);

        // constructor
        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null);
        e.load_this();
        e.load_args();
        e.super_invoke_constructor(CSTRUCT_CLASS);
        e.return_value();
        e.end_method();
        ......
}

也是通过 CodeEmitter 来生成字节码文件。

3.5.6 生成的代理类

public class T$$FastClassByCGLIB$$3ad7f32f extends FastClass {
    public T$$FastClassByCGLIB$$3ad7f32f(Class var1) {
        super(var1);
    }

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

        return -1;
    }

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

        return -1;
    }

    public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }

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

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

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

    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        T var10000 = new T;
        T var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

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

    public int getMaxIndex() {
        return 3;
    }
}
  • 可以看到继承自 FastClass 类。
  • 最大的作用就是为目标类每个方法都设置了索引 index,因此当调用目标实例方法时,那就可以直接使用目标实例调用方法,而不需要使用反射了。
public class T$$EnhancerByCGLIB$$422fccc9$$FastClassByCGLIB$$4e16ba3f extends FastClass {
    public T$$EnhancerByCGLIB$$422fccc9$$FastClassByCGLIB$$4e16ba3f(Class var1) {
        super(var1);
    }

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

        return -1;
    }
    ......
}

这个是代理类所有方法的索引。

3.6 小结

cglib 代理方法调用为什么比动态代理快,就是因为cglib 代理会直接通过目标实例调用对应的方法,而动态代理只能通过反射方式。
但是如果使用 MethodProxy 方式调用,第一次的情况下,需要生成目标类和代理类的 FastClass 字节码文件,这个比较耗时。如果你只调用一次的话,那么使用 Method 直接反射调用。

你可能感兴趣的:(JVM_cglib技术原理分析)