Skip to the content.

1-2.获取自适应扩展

通过1-0.SPI可以知道,ExtensionLoader创建的具体实现都是自适应扩展ExtensionLoader通过getAdaptiveExtension()方法获取自适应扩展:

public T getAdaptiveExtension() {
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {
        if (createAdaptiveInstanceError == null) {
            // 双重加锁同步
            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        // 没有则创建新的
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        } else {
            throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
        }
    }
    return (T) instance;
}

对于每一个接口来说,只需要生成一个自适应代理自适应代理会将方法代理到具体的实现类。因此自适应代理只需要缓存一个,即cachedAdaptiveInstance。真正的创建自适应代理是在createAdaptiveExtension()方法中。

private T createAdaptiveExtension() {
    try {
        // 依赖注入
        return injectExtension((T)
        // 获取自适应扩展类的Class对象
        getAdaptiveExtensionClass()
        // 通过反射创建实例
        .newInstance());
    } catch (Exception e) {
        throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    }
}

对于injectExtension(...)在之前的1-1.获取扩展类实现已经介绍过了,这里主要介绍如何获取自适应扩展类的Class对象。

现在已知的获取自适应扩展类的Class对象的方法有两种:

  1. 通过给自定义的扩展类添加@Adaptive注解,关于这点可以参考1-1.获取扩展类实现
  2. 通过Dubbo自动生成自适应扩展类,即createAdaptiveExtensionClass()方法;
private Class<?> getAdaptiveExtensionClass() {
    // 获取所有扩展类实例
    getExtensionClasses();
    // 如果cachedAdaptiveClass不为空
    // 则证明出现了第一种情况
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    // 通过Dubbo创建自适应扩展类
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

对于JVM来说Class类文件的形式可以有很多种,可以参考JVM虚拟机类加载机制笔记,因此,我们可以使用JVM的机制动态加载Class文件。createAdaptiveExtensionClass()就是通过该方式处理的,不过区别是Dubbo不是直接生成Class文件,而是生成源代码,然后编译、加载:

private Class<?> createAdaptiveExtensionClass() {
    // 生成Java代码
    String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
    // 获取类加载器
    ClassLoader classLoader = findClassLoader();
    // 获取编译器
    org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    // 编译代码,获取Class文件
    return compiler.compile(code, classLoader);
}

这个方法中,我们主要关心的有两部分:

  1. AdaptiveClassCodeGenerator如何生成代码的
  2. Compiler如何编译源代码生成Class对象的

我们对这两部分分别进行讨论。

1.1 AdaptiveClassCodeGenerator

AdaptiveClassCodeGenerator是自适应扩展类的代码生成器。