背景

  • 首先我们根据配置来进行 SPI 扩展的加载,但是我不想在启动的时候让扩展被加载,而是根据请求参数来动态选择对应的扩展。
  • Dubbo 通过一个代理机制实现了自适应扩展,简单来说就是为你想拓展的接口生成一个代理类,可以通过JDK 或者 javassist编译你生成的代理类代码,然后通过反射创建实例。
  • 这个实例里面的实现会根据本来方法的请求参数得知需要的扩展类,然后通过 ExtensionLoader.getExtensionLoader(type.class).getExtension() 来获取真正的实例来调用。
  • @Adptive 注解就是自适应扩展相关的注解,可以修饰类和方法上;修饰类的时候不会生成代理类,类本身就是代理类,修饰方法上的时候会生成代理类。


修饰类

EXtensionFactory接口
  • AdaptiveExtensionFactory 用@Adptive修饰
  • SpiExtensionFactory
  • SpringExtensionFactory

或者ExtensionLoader类的构造函数也会通过 getAdaptiveExtension() 获取指定的扩展类的 ExtensionFactory

private ExtensionLoader(Class<?> type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
AdaptiveExtensionFactory
  • 构造函数缓存所有的实现类
  • getExtension() 返回缓存的一个实现类
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List<ExtensionFactory> factories;
    
    // 缓存所有的ExtensionFactory的实现类
    public AdaptiveExtensionFactory() {
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
        for (String name : loader.getSupportedExtensions()) {
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

  
    // 获取实例的时候遍历factory,只要有一个找到就返回
    @Override
    public <T> T getExtension(Class<T> type, String name) {
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }

}
getAdaptiveExtension()
  • 先从缓存中获取,如果没有则通过双重检测,调用 createAdaptiveExtension() 来创建实例。
public T getAdaptiveExtension() {
  
        // 从缓存中获取实例
        Object instance = cachedAdaptiveInstance.get();
  
        // 双重检测 创建实例 createAdaptiveExtension()
        if (instance == null) {
            if (createAdaptiveInstanceError == null) {
                synchronized (cachedAdaptiveInstance) {
                    instance = cachedAdaptiveInstance.get();
                    if (instance == null) {
                        try {
                            instance = createAdaptiveExtension();
                            cachedAdaptiveInstance.set(instance);
                        } 
                        
                        ···························
                          
        }

        return (T) instance;
    }
createAdaptiveExtension
  • 通过调用 getAdaptiveExtensionClass() 创建一个实例
  • 并调用 injectExtension() 进行依赖注入
  private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } 
        ····················
    }
getAdaptiveExtensionClass
  • 调用 getExtensionClasses() 之前分析过,主要过程就是获取路径下的对应接口的所有实现类,并缓存;参考 getExtensionClasses
  • 如果类上面有 @Adaptive 注解修饰直接返回,如果没有动态生成类
 private Class<?> getAdaptiveExtensionClass() {
        getExtensionClasses();
        
        // 如果有Adaptive注解在类上,直接返回该类
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
   
        // 如果没有说明需要动态生成类
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }


修饰方法

  • @Adaptive 注解在方法上则需要动态拼接代码,然后动态生成类
createAdaptiveExtensionClass
  • 调用 createAdaptiveExtensionClassCode()
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();
        return compiler.compile(code, classLoader);
    }




    private String createAdaptiveExtensionClassCode() {
        StringBuilder codeBuilder = new StringBuilder();
        Method[] methods = type.getMethods();
        boolean hasAdaptiveAnnotation = false;
         
        ·····················
          
       
    }


参考