(一)dubbo源码分析之SPI机制

  • 概述
    duobo的SPI机制贯穿于duobbo的整个架构,dubbo架构上是分层的,每层之间是面向接口的,每个接口具体使用哪个实现去提供服务于上层,这个时候就会触发dubbo的SPI机制,dubbo的每层接口都是一个扩展点,这个时候用哪个实现会有一个拓展适配器的东西去根据SPI接口传递的参数实例化具体提供服务的实现类。其实SPI机制还可以理解为文件方式配置的简单工厂模式,拓展适配器就是那个简单工厂。

  • Demo

    /**
     * @author wuxinxin
     */
    @SPI
    public interface Animal {
          
          
    
        void say();
    
    }
    
    /**
     * @author wuxinxin
     */
    public class Pig implements Animal {
          
          
        public void say() {
          
          
            System.out.println("猪叫");
        }
    }
    
    
    /**
     * @author wuxinxin
     */
    public class SpiTest {
          
          
    
        public static void main(String[] args) {
          
          
    
            ExtensionLoader<Animal> extensionLoader = ExtensionLoader.getExtensionLoader(Animal.class);
    
            Animal pig = extensionLoader.getExtension("pig");
    
            pig.say();
    
        }
    
    }
    
    //配置文件classpath: META-INF/dubbo/com.example.dubbo.spi.Animal
    pig = com.example.dubbo.spi.Pig
    dog = com.example.dubbo.spi.Dog
    
  • 源码分析

    
     功能:创建某个类型的ExtensionLoader对象
     
     private ExtensionLoader(Class<?> type) {
          
          
        this.type = type;
        //这个objectFactory就是拓展点适配器
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
    
    
    @SuppressWarnings("unchecked")
    //静态方法直接调用getExtensionLoader获取某种class的ExtensionLoader对象
    public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
          
          
        if (type == null) {
          
          
            throw new IllegalArgumentException("Extension type == null");
        }
        if (!type.isInterface()) {
          
          
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        if (!withExtensionAnnotation(type)) {
          
          
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        //EXTENSION_LOADERS是一个<Class<?>, ExtensionLoader<?>>的Map,用作缓存
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
          
          
        	//如果当前类型没有创建ExtensionLoader对象,那么进行创建
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
    
    
    功能:加载拓展点的所有实现(拓展点适配器是一个特殊的实现)
    
    public T getAdaptiveExtension() {
          
          
    		//cachedAdaptiveInstance是缓存拓展点适配器对象的
            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;
        }
    //createAdaptiveExtension
    @SuppressWarnings("unchecked")
    private T createAdaptiveExtension() {
          
          
        try {
          
          
            //1.获取适配器类型的class对象
            //2.获取到class对象后,创建适配器对象
            //3.给适配器的set方法进行注入依赖的对象,毕竟适配器对象不是spring管理的,是运行时产生的
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
          
          
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
    //getAdaptiveExtensionClass
    private Class<?> getAdaptiveExtensionClass() {
          
          
    	//获取当前type类型(拓展点的)的所有实现的class,先不创建实例,懒加载方式
        getExtensionClasses();
        //cachedAdaptiveClass代表拓展点适配器class,也是缓存在ExtensionLoader对象中
        if (cachedAdaptiveClass != null) {
          
          
        	//如果存在,直接返回拓展点适配器class
        	//cachedAdaptiveClass有可能在获取所有实现的时候能获取到,有可能获取不到
            return cachedAdaptiveClass;
        }
        //如果不存在,直接创建拓展点适配器class,使用动态字节码生成
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
    
    // 加载拓展点的所有实现,获取type指定类型命名的文件,解析缓存到ExtensionLoader中
    private Map<String, Class<?>> loadExtensionClasses() {
          
          
        cacheDefaultExtensionName();
    
        Map<String, Class<?>> extensionClasses = new HashMap<>();
        //DUBBO_INTERNAL_DIRECTORY=>META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory(Type)
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        return extensionClasses;
    }
    META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
    //看到配置,很明显ExtensionFactory这个拓展点接口有三个实现
    //拓展点适配器实现:AdaptiveExtensionFactory
    //拓展点普通实现:SpiExtensionFactory,SpringExtensionFactory
    adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
    spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
    spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
    
    //根据以拓展点全路径名称查找相应文件,加载到拓展点的全部实现配置,配置如上
    private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
          
          
        try {
          
          
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
          
          
                String line;
                while ((line = reader.readLine()) != null) {
          
          
                    final int ci = line.indexOf('#');
                    if (ci >= 0) {
          
          
                        line = line.substring(0, ci);
                    }
                    line = line.trim();
                    if (line.length() > 0) {
          
          
                        try {
          
          
                            String name = null;
                            int i = line.indexOf('=');
                            if (i > 0) {
          
          
                                name = line.substring(0, i).trim();
                                line = line.substring(i + 1).trim();
                            }
                            //获取一行配置,根据=号分割
                            //比如name=adaptive                           
                            //line=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
                            if (line.length() > 0) {
          
          
                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                            }
                        } catch (Throwable t) {
          
          
                            IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                            exceptions.put(line, e);
                        }
                    }
                }
            }
        } catch (Throwable t) {
          
          
            logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", class file: " + resourceURL + ") in " + resourceURL, t);
        }
    }
    //进行拓展点实现的class,并且缓存到ExtensionLoader相应的属性中
    private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
          
          
        if (!type.isAssignableFrom(clazz)) {
          
          
            throw new IllegalStateException("Error occurred when loading extension class (interface: " +
                    type + ", class line: " + clazz.getName() + "), class "
                    + clazz.getName() + " is not subtype of interface.");
        }
        //如果这个实现有@Adaptive,那么这个就是拓展点适配器实现,是一个特殊的拓展点实现
        if (clazz.isAnnotationPresent(Adaptive.class)) {
          
          
        //赋值给ExtensionLoader的cachedAdaptiveClass属性
            cacheAdaptiveClass(clazz);
        } else if (isWrapperClass(clazz)) {
          
          
            cacheWrapperClass(clazz);
        } else {
          
          
        //这个是真正提供拓展点功能的普通实现,将相应的class全部加载
            clazz.getConstructor();
            if (StringUtils.isEmpty(name)) {
          
          
                name = findAnnotationName(clazz);
                if (name.length() == 0) {
          
          
                    throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
                }
            }
    
            String[] names = NAME_SEPARATOR.split(name);
            if (ArrayUtils.isNotEmpty(names)) {
          
          
                cacheActivateClass(clazz, names[0]);
                for (String n : names) {
          
          
                    cacheName(clazz, n);
                    //真正使用到的实现缓存起来,存在ExtensionLoader的cachedClasses属性
                    saveInExtensionClass(extensionClasses, clazz, name);
                }
            }
        }
    }
    
    功能:使用上面创建的ExtensionLoader对象,根据name创建相应需要的拓展点实现
     public T getExtension(String name) {
          
          
            if (StringUtils.isEmpty(name)) {
          
          
                throw new IllegalArgumentException("Extension name == null");
            }
            if ("true".equals(name)) {
          
          
                return getDefaultExtension();
            }
            //从缓存(cachedInstances)中获取当前拓展点的需要的实现,根据name参数
            Holder<Object> holder = getOrCreateHolder(name);
            Object instance = holder.get();
            if (instance == null) {
          
          
                synchronized (holder) {
          
          
                    instance = holder.get();
                    if (instance == null) {
          
          
                    //如果没创建过需要的拓展点实现,那么临时创建
                        instance = createExtension(name);
                        //将创建的拓展点实现保存在缓存中
                        holder.set(instance);
                    }
                }
            }
            return (T) instance;
        }
        //创建需要的拓展点实现(ExtensionLoader只是加载了class对象,并没有创建实例)
    private T createExtension(String name) {
          
          
            Class<?> clazz = getExtensionClasses().get(name);
            if (clazz == null) {
          
          
                throw findException(name);
            }
            try {
          
          
                T instance = (T) EXTENSION_INSTANCES.get(clazz);
                if (instance == null) {
          
          
                   //创建拓展实现,缓存起来
                    EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                    instance = (T) EXTENSION_INSTANCES.get(clazz);
                }
                //因为这些拓展实现是在容器启动后创建的,spring容器已经初始化完成,需要手动实现依赖注入
                injectExtension(instance);
                Set<Class<?>> wrapperClasses = cachedWrapperClasses;
                if (CollectionUtils.isNotEmpty(wrapperClasses)) {
          
          
                    for (Class<?> wrapperClass : wrapperClasses) {
          
          
                        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                    }
                }
                return instance;
            } catch (Throwable t) {
          
          
                throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                        type + ") couldn't be instantiated: " + t.getMessage(), t);
            }
        }
    
  • 总结
    dubbo的SPI机制其实也很简单,就是把实现以key/value的形式都提前放在对应的文件中,然后需要的时候去获取对应的实现
    1.getExtensionLoader方法核心功能就是创建ExtensionLoader对象,一个type对应一个ExtensionLoader,加载type类型的所有实现的class对象缓存在ExtensionLoader
    2.getExtension方法核心功能就是根据当前的ExtensionLoader对象,获取名称为name的拓展点实现实例返回,并且缓存起来。
    3.拓展点适配器是一个特殊的拓展点实现,这个有时候用来做选择拓展实现的策略的,起到一个适配器的作用,是一个特殊的拓展点实现,不一定需要。
    4.任何扩展点触发SPI,都会先创建ExtensionFactory的ExtensionLoader,出于简单考虑,读者最好先去获取
    ExtensionFactory这个扩展点进行试验,非ExtensionFactory的拓展点其实是getExtension才去真正加载拓展点的所有实现,先默认递归获取ExtensionFactory的拓展实现

猜你喜欢

转载自blog.csdn.net/weixin_38312719/article/details/105929243