dubbo自适应拓展机制 - litter-fish/ReadSource GitHub Wiki

原理

     自适应拓展机制的实现逻辑:

  1. 首先 Dubbo 会为拓展接口生成具有代理功能的代码。
  2. 然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。
  3. 最后再通过反射创建代理类,整个过程比较复杂

Adaptive 注解

  

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})// Adaptive 可注解在类或方法上
public @interface Adaptive {
    String[] value() default {};
}
  1. 当 Adaptive 注解在类上时,Dubbo 不会为该类生成代理类。     AdaptiveCompiler 和 AdaptiveExtensionFactory,此种情况,     表示拓展的加载逻辑由人工编码完成
  2. 注解在方法(接口方法)上时,Dubbo 则会为该方法生成代理逻辑,表示拓展的加载逻辑需由框架自动生成

获取自适应拓展

// com/alibaba/dubbo/common/extension/ExtensionLoader.java
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("fail to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        } else {
            throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
        }
    }

    return (T) instance;
}

创建自适应拓展

// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
  * 1. 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
  * 2. 通过反射进行实例化
  * 3. 调用 injectExtension 方法向拓展实例中注入依赖,为手工编码的自适应拓展注入依赖
  */
private T createAdaptiveExtension() {
    try {
        // 获取自适应拓展类,并通过反射实例化
        return
                injectExtension( // 调用 injectExtension 方法向拓展实例中注入依赖, 为手工编码的自适应拓展注入依赖
                        (T) getAdaptiveExtensionClass() // 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
                                .newInstance()); // 通过反射进行实例化
    } catch (Exception e) {
        throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    }
}

获取自适应拓展 Class 对象

// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
 * 首先,getExtensionClasses 这个方法用于获取某个接口的所有实现类。
 * 比如该方法可以获取 Protocol 接口的 DubboProtocol、HttpProtocol、InjvmProtocol 等实现类。
 * 在获取实现类的过程中,如果某个某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量。
 * 此时,上面步骤中的第二步条件成立(缓存不为空),直接返回 cachedAdaptiveClass 即可。
 * 如果所有的实现类均未被 Adaptive 注解修饰,那么执行第三步逻辑,创建自适应拓展类
 * @return
 */
private Class<?> getAdaptiveExtensionClass() {
    // 通过 SPI 获取所有的拓展类
    getExtensionClasses();
    // 检查缓存,若缓存不为空,则直接返回缓存
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    // 创建自适应拓展类
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

创建自适应拓展类

// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
 * createAdaptiveExtensionClass 方法用于生成自适应拓展类,该方法首先会生成自适应拓展类的源码,
 * 然后通过 Compiler 实例(Dubbo 默认使用 javassist 作为编译器)编译源码,得到代理类 Class 实例
 * @return
 */
private Class<?> createAdaptiveExtensionClass() {
    // 构建自适应拓展代码
    String code = createAdaptiveExtensionClassCode();
    ClassLoader classLoader = findClassLoader();
    // 获取编译器实现类
    com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    // 编译代码,生成 Class
    return compiler.compile(code, classLoader);
}