动态代理原理详解(2) - CGLIB实现
发布于 / 2016-08-14
简介:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
1. CGLIB简介
在前面动态代理原理详解(一)——JDK实现一文中介绍了JDK默认实现的动态代理功能,JDK动态代理简单易用,底层实现也非常清晰明了,但它只能对接口进行代理,无法为未实现接口的普通类进行代理,这是它最大的缺陷。在这篇文章中将讲解另一个动态代理库——CGLIB。
CGLIB(Code Generator Library)是一个高性能的代码生成库,被广泛应用于AOP框架(Hibernate、Spring、Dynaop)中以提供方法拦截功能,主要以继承目标类的方式来进行拦截实现,因此CGLIB可以对无接口的类进行代理,但这也是CGLIB存在短板的原因所在,它无法代理final修饰的类或方法,因为final类无法被继承,同时final方法无法被重写。
CGLIB代理主要通过操作字节码的方式为对象引入方法调用时访问操作,底层使用了ASM来操作字节码生成新的类,ASM是一个短小精悍的字节码操作框架。CGLIB的应用栈如下:
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);
- }
- }
该方法的主要流程是先找到类对象,然后根据类对象生成需要的相应的实例;这里先讲解一下获取类对象的流程细节:
- 首先尝试从缓存加载对应的类对象,此处用到的缓存是
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存储了当前缓存的所有生成类的类名,用于检测生成类的类名是否重复。
- 如果不能从缓存
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
,记住这个命名。
- 如果尝试使用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$Method
和CGLIB$getInfo$1$Method
记录下来。同时通过CGLIB提供的MethodProxy的create(Class, Class, String, String, String)
方法创建两个方法的MethodProxy方法代理对象,并分别使用属性CGLIB$run$0$Proxy
和CGLIB$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)
方法时,传入的前两个参数var1
和var0
已经被置为了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对象,使用属性sig1
和sig2
对原始方法和代理方法进行记录和关联,构造了一个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的hashCode
,helper(ci, ci.c2)
方法中生成的FastClass代理类Class文件名应该是com.coderap.proxy.cglib.Bugatti$$FastClassByCGLIB$$ + key的hashCode
。两次helper(CreateInfo, Class)
最终会生成的目标类和代理类的FastClass对象,并被FastClassInfo对象分别使用f1
和f2
两个属性记录下来,同时使用它们的getIndex(Signature)
方法来获取f1
和f2
分别在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还有很多其他的高级用法,但底层生成代理类的的原理都是类似的。这里对本文所讲解的内容进行总结。
- CGLIB可以为没有实现任何接口的目标类生成代理类,因为它是通过继承目标类的方式来实现动态代理的,但正是由于继承的特性,CGLIB无法为final修饰的类或方法生成代理。
- CGLIB底层使用了ASM进行字节码文件的生成和操作。
- CGLIB使用了缓存机制对已经生成的代理类进行缓存,减少每次重新生成带来的性能消耗。
- CGLIB会使用FastClass机制将代理类中的方法使用索引方式进行标注,减少因反射调用带来的性能消耗。
推荐阅读
Java多线程 46 - ScheduledThreadPoolExecutor详解(2)
ScheduledThreadPoolExecutor用于执行周期性或延时性的定时任务,它是在ThreadPoolExe...