首页 > 编程语言 >【代理】【四】代理源码解析-Cglib代理-Generator代理对象创建过程

【代理】【四】代理源码解析-Cglib代理-Generator代理对象创建过程

时间:2023-03-03 22:13:51浏览次数:40  
标签:缓存 Generator EnhancerKey create 代理 源码 KeyFactory gen

1  前言

 上节我们简单感受了下Cglib的一个代理过程,并且我也说到了Enhancer 创建代理的时候,首先会创建对象Key出来,用于标识这个类以及将其作为缓存的Key,然后再创建代理对象并放进缓存,那么这节我们就来看下执行的一个具体过程。

2  源码分析

2.1  Key创建的时机

首先我们先来看下是什么时候需要创建Key的,

// EnhancerKey
public Object create() {
    classOnly = false;
    argumentTypes = null;
    return createHelper();
}
// Key对象
private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class);
private Object createHelper() {
    validate();
    if (superclass != null) {
        setNamePrefix(superclass.getName());
    } else if (interfaces != null) {
        setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
    }
    // 这里就需要先创建被代理对象的 Key 出来,再调用父类进行代理对象的创建
    return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
                                                ReflectUtils.getNames(interfaces),
                                                filter,
                                                callbackTypes,
                                                useFactory,
                                                interceptDuringConstruction,
                                                serialVersionUID));
}

看这行代码  private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class);可以看到我们的 Key 对象(即 EnhancerKey)是需要借助 KeyFactory 来进行创建的,我们看下:

// KeyFactory
public static KeyFactory create(Class keyInterface) {
    // 调用重载方法
    return create(keyInterface, null);
}
public static KeyFactory create(Class keyInterface, Customizer customizer) {
    // 继续调用重载方法
    return create(keyInterface.getClassLoader(), keyInterface,  customizer);
}
// 通过 Generator 进行创建
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
    Generator gen = new Generator();
    // 设置接口 其实就是 EnhancerKey.class
    gen.setInterface(keyInterface);
    // customizer为null
    gen.setCustomizer(customizer);
    // 即 keyInterface.getClassLoader()
    gen.setClassLoader(loader);
    // 创建
    return gen.create();
}
public static class Generator extends AbstractClassGenerator {
    public KeyFactory create() {
      setNamePrefix(keyInterface.getName());
     // super.create 返回的是 Object 为什么能强转为 KeyFactory?   return (KeyFactory)super.create(keyInterface.getName()); } }

我看完有两个疑问:

  • Generator 的 create 方法返回的是 Object对象为什么能强转为 KeyFactory ?
  • KeyFactory 为什么又能强转为 EnhancerKey  ?

那么我们带着这样的疑问来看下具体的创建过程是怎么样的。

2.2  创建过程

2.2.1  KeyFactory - create

我们就从这里开始,我们的 EnhancerKey 是由 KeyFactory 里的 Generator 来创建的:

// 通过 Generator 进行创建 keyInterface 即 EnhancerKey.class
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
    Generator gen = new Generator();
    // 设置接口 其实就是 EnhancerKey.class
    gen.setInterface(keyInterface);
    // customizer为null
    gen.setCustomizer(customizer);
    // 即 keyInterface.getClassLoader()
    gen.setClassLoader(loader);
    // 创建
    return gen.create();
}

2.2.2 Generator - create 创建代理

那我们进入 Generator 看一下里边是如何创建的:

public static class Generator extends AbstractClassGenerator {
    // 缓存
    private static final Source SOURCE = new Source(KeyFactory.class.getName());
    // 接口
    private Class keyInterface;
    // 个性化
    private Customizer customizer;
    private int constant;
    private int multiplier;
    public Generator() {
        super(SOURCE);
    }
    public KeyFactory create() {
        // 设置名称前缀
        setNamePrefix(keyInterface.getName());
        // 调用父类创建代理对象
        return (KeyFactory)super.create(keyInterface.getName());
    }
}

我们首先看下 Generator 的初始化方法,是调用父类的,那么我们看一下父类即就是我们的 AbstractClassGenerator 的初始化:

abstract public class AbstractClassGenerator
implements ClassGenerator
{
    private static final Object NAME_KEY = new Object();
    
    private Source source;
    // Source内部类 缓存
    protected static class Source {
        String name;
        // 缓存
        Map cache = new WeakHashMap();
        public Source(String name) {
            this.name = name;
        }
    }
    // 初始化缓存
    protected AbstractClassGenerator(Source source) {
        this.source = source;
    }
}

2.2.3 AbstractClassGenerator - create 创建代理

看见初始化就是初始化缓存变量的值,那么我们继续看 Generator 的 create 方法,也是调用父类 AbstractClassGenerator 的create方法,我们来看下具体的源码:

protected Object create(Object key) {
    try {
        Class gen = null;
        synchronized (source) {
            // 获取类加载器
            ClassLoader loader = getClassLoader();
            Map cache2 = null;
            // 先判断缓存中有没有
            cache2 = (Map)source.cache.get(loader);
            /**
             * 缓存为空说明不存在,初始化缓存
             * 这里注意一点 cache2 = new HashMap();
             * cache2.put(NAME_KEY, new HashSet()) 往 hashMap中放入 NAME_KEY -> newHashSet()
             * source.cache.put(loader, cache2); 往缓存中放入 loader -> cache2
             * 那么我们的缓存结构就是 <loader, <NAME_KEY, newHashSet()>> 嵌套型的
             */
            if (cache2 == null) {
                cache2 = new HashMap();
                // 初始化 cache2
                cache2.put(NAME_KEY, new HashSet());
                // 初始化缓存
                source.cache.put(loader, cache2);
            } else if (useCache) {
                // 先从缓存中获取
                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;
                    // 默认为false 暂时不用管
                    if (attemptLoad) {
                        try {
                            gen = loader.loadClass(getClassName());
                        } catch (ClassNotFoundException e) {
                            // ignore
                        }
                    }
                    /**
                     * 这里就会根据策略进行创建了
                     * strategy 默认的实现为
                     * private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
                     */
                    if (gen == null) {
                        // 创建出代理对象类字节数组
                        byte[] b = strategy.generate(this);
                        /**
                         * 这里的缓存放置的是
                         * <loader,<NAME_KEY, HashSet>>
                         * 这里就是把 className 放进了对应的 HashSet里
                         */
                        String className = ClassNameReader.getClassName(new ClassReader(b));
                        getClassNameCache(loader).add(className);
                        // 生成类的定义文件
                        gen = ReflectUtils.defineClass(className, b, loader);
                    }
                    // 默认开启缓存,如果开启缓存
                    if (useCache) {
                        /**
                         *  放入缓存
                         *  注意上边也放了一次缓存,这里又放了一次 注意两次不一样哈
                         *  这次放的是 key -> WeakReference(gen)
                         *  key 即 EnhancerKey
                         *  val 是 外边包了一层WeakReference的用于创建代理对象的类定义信息,
                         *        也就是下一次如果缓存开启的话直接获取定义信息来创建代理对象即可
                         *  那么我们的source缓存 又呈现<loader,<EnhancerKey, WeakReference(gen)>>
                         */
                        cache2.put(key, new WeakReference(gen));
                    }
                    // 创建代理对象 抽象方法也就是调用子类的方法
                    return firstInstance(gen);
                } finally {
                    CURRENT.set(save);
                }
            }
        }
        return firstInstance(gen);
    } catch (RuntimeException e) {
        throw e;
    } catch (Error e) {
        throw e;
    } catch (Exception e) {
        throw new CodeGenerationException(e);
    }
}

那我们大致总结一下执行过程:

  • 先看缓存中有没有;
  • 没有的话,初始化NAME_KEY缓存;
  • 调用默认策略进行代理对象类字节数组的生成;
  • 调用子类的 firstInstance 创建代理对象。

那么我们再着重看一下默认策略的执行过程:

public class DefaultGeneratorStrategy implements GeneratorStrategy {
    public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
    
    public byte[] generate(ClassGenerator cg) throws Exception {
        ClassWriter cw = getClassWriter();
        // 就是调用子类的 generateClass 方法
        transform(cg).generateClass(cw);
        return transform(cw.toByteArray());
    }

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

发现其就是调用子类的  generateClass 方法。

好了到这里为止,我们可以发现 EnhancerKey 本身是个接口,通过 KeyFactory里的 Generator为其床创建代理对象,创建代理对象的两个步骤就是1、调用子类的 generateClass方法获取到代理对象的类字节信息。2、调用子类的firstInstance 方法创建代理对象的。不知道你晕没晕,那么我们接下里就要看什么了?是不是要看一下 Generator 里的 generateClass 和 firstInstance 方法啦。

2.3  Generator - generateClass 

我们来看下 Generator 的 generateClass 方法:

public void generateClass(ClassVisitor v) {
    // ClassEmitter 对 asm 的classAdapter和MethodAdapter的实现,贯穿于cglib代码的处理
    ClassEmitter ce = new ClassEmitter(v);
    // 找到接口中的方法名字不是newInstance的以及返回值类型不是Object的就报错
    Method newInstance = ReflectUtils.findNewInstance(keyInterface);
    if (!newInstance.getReturnType().equals(Object.class)) {
        throw new IllegalArgumentException("newInstance method must return Object");
    }
    /**
     * 下边就是生成类的信息 做收集做汇总转换
     * 我这里不深入不看了,只做了解 大概知道是什么就可以了哈
     */
    // 获取参数的类型
    Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
    ce.begin_class(Constants.V1_2,
                   Constants.ACC_PUBLIC,
                   getClassName(),
                   KEY_FACTORY,  // 看这里 KEY_FACTORY 也就是代理类是继承 KeyFactory的
                   new Type[]{ Type.getType(keyInterface) }, // 看这里接口 就是你那个 EnhancerKey
                   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();
    
    // hash code方法
    ...// equals方法
    ...// toString方法
    ...
    e.return_value();
    e.end_method();
    ce.end_class();
}

到这里我们就恍然大悟了,我们的代理对象创建出来就会继承 KeyFactory,并且实现 EnhancerKey 接口。这就解决了我们上边的两个疑惑哈。

2.4  Generator - firstInstance 

那么我们最后再来看下 firstInstance 的东西:

protected Object firstInstance(Class type) {
    return ReflectUtils.newInstance(type);
}

比较简单了哈,就是反射获取构造器创建代理对象的实例完工。

3  生成的代理对象类信息

那我们看下最后生出来的代理对象类长什么样子,看其实就是属性和两个构造器以及Object中的几个方法(这几个方法就不贴了哈比较多)。

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;
    }
... }

4  小结

好了本节我们主要看了一下 EnhancerKey 代理创建的过程,它主要用于 Enhancer 的 key,至于为什么要这么要这么做,还着实有点不太懂为什么哈,希望知道的小伙伴告知下,有理解不对的地方欢迎指正哈。

标签:缓存,Generator,EnhancerKey,create,代理,源码,KeyFactory,gen
From: https://www.cnblogs.com/kukuxjx/p/17176865.html

相关文章

  • Apache设置反向代理解决js跨域问题
    这是一个很简单的方案,通过启用Apache反向代理解决js跨域问题为什么要这么做?在现在的开发过程中大家会遇到这样一个问题:后端代码写好之后,前端的小伙伴需要将后端代码部署......
  • 【代理】【三】代理源码解析-Cglib代理-环境准备以及简单介绍
    1 前言之前我们看过了JDK动态代理的源码了,今天我们大概花三四篇(因为一篇文章东西太多写的人费劲看的人也累哈)来看看Cglib的代理源码过程,其中涉及到asm包中的东西构建类......
  • 互联网医院源码搭建|互联网医院发展过程中遇到的问题
       互联网医疗分为互联网医院、互联网+医院两种模式,互联网+医院目前看已经算比较成熟了,几乎大的医院都是app或者公众号的预约、挂号、缴费、自助机一体化。目前真正难......
  • DK 动态代理和 CGLIB 动态代理的区别是什么?
    Java中实现动态代理有两种方式:JDK动态代理和CGLIB动态代理。动态代理的主要作用是在不改变原有代码的情况下,对原有代码进行增强。JDK动态代理JDK动态代理具体实现步骤:......
  • 代理异常捕获
    背景在某些场景,比如过滤器,拦截器,或者某些代理类的时候,ControllerAdvance是捕获不到异常的方案:使用springmvc框架,让程序直接导入进来//验证etbc登录try{......
  • 手把手教你使用LabVIEW人工智能视觉工具包快速实现传统Opencv算子的调用(含源码)
    (文章目录)前言今天我们一起来使用LabVIEWAI视觉工具包快速实现图像的滤波与增强;图像灰度处理;阈值处理与设定;二值化处理;边缘提取与特征提取等基本操作。工具包的安装与下......
  • 9_Spring_JDK动态代理
    ​ 代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。房产中介代替业主卖房 静态代理     ......
  • 9_Spring_JDK动态代理
    ​ 代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。房产中介代替业主卖房 静态代理     ......
  • 成品直播源码,Flutter 夜间模式 全局字体
    成品直播源码,Flutter夜间模式全局字体 import'package:flutter/material.dart';import'package:flutter_widget/router/applicationRouterGradual.dart';import'pa......
  • 直播平台搭建源码,canvas 画一条波浪线 进度条
    直播平台搭建源码,canvas画一条波浪线进度条<template> <view>  <canvas:style="{'width':width+'rpx','height':height +'rpx','backgroundColor':'#d2d......