Dubbo的SPI扩展机制(上)

181 阅读14分钟

RPC实现原理

RPC定义

RPC(Remote Procedure Call)远程过程调用,Remote Procedure Call Protocol是一个计算机通信协议。 它允许像调用本地方法一样调用远程服务。由于不在同一个内存空间,不能直接调用,需要通过网络来传达调用语义和传达调用的数据。

image.png

RPC调用过程

  • 远程代理
  • 序列化
  • 网络传输
  • 反序列化

Dubbo应用整体设计

  • config 配置层,对外配置接口,以ServiceConfig和ReferenceConfig两个实现为中心,初始化配置信息
  • proxy 服务代理层,Dubbo会为生产者和消费者生成代理类,用于远程调用,通过代理业务层对远程调用无感知
  • registry 注册中心层,封装服务地址的注册与发现
  • cluster 集群容错层,也叫路由层,封装调用失败容错机制,以及对多个provider节点的路由及负载均衡
  • monitor 监控层,记录RPC调用次数和调用时间监控
  • protocol 远程调用层,封装RPC调用过程,服务暴露和引用的功能入口
  • exchange 信息交换层,封装请求响应模式,同步转异步
  • transport 网络传输层,抽象mina和netty为统一接口,在其上封装一层接口方便扩展
  • serialize 数据序列化层,负责传输数据的序列化和反序列化

image.png

Dubbo概述及使用

Dubbo总体分为业务层(Business)、RPC层、Remote层三大层。从程序员开发角度又分为API层和SPI层,其中Service和Config属于API层,其它都属于SPI层。

Dubbo的SPI机制

Dubbo的SPI机制是对Java SPI 机制的升级与拓展,它在Java SPI基础上扩展了 IoC 和 AOP。

SPI(Service Provider Interface),是java提供的一套用来被第三方实现或者扩展的接口,可以用来启用框架扩展和替换组件。SPI的作用就是为这些被扩展的API寻找服务实现。

API(Application Programming Interface)实现方制定的接口实现,供开发人员调用。简单来说就是实现方开发出来哪些接口,调用者就只有选择权,没有拓展权。

SPI(Service Provider Interface),由调用方指定接口规范,提供给外部实现,调用方在调用时选择自己需要的外部实现。一般被框架拓展人员使用。

Java SPI 规定jar包读取的路径必须为 META-INF/services(文件接口名完整包路径)

/**
 * 不能按需加载
 * 不够灵活,不能动态的AOP和IOC
 * dubbo SPI
 */
public class JdkSpiMain {

    public static void main(String[] args) {
        ServiceLoader<JdkSpiServiceInterface> serviceLoader = ServiceLoader.load(JdkSpiServiceInterface.class);
        Iterator<JdkSpiServiceInterface> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            JdkSpiServiceInterface spiInterface = iterator.next();
            spiInterface.getColor();
        }
    }
}

Dubbo源码

定义@SPI注解,标识接口为可拓展的。

package org.apache.dubbo.common.extension;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SPI {
    String value() default "";

}

image.png

定义@Adaptive注解,保证dubbo内部调用具体实现时适配机制,而不是硬编码实现。

package org.apache.dubbo.common.extension;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Adaptive {
    String[] value() default {};
}

Dubbo SPI机制拓展支持AOP 和 IOC

@SPI
public interface Car { 

    public void getColor();

    @Adaptive("car")
    public void  getColorForUrl(URL url);

}

创建一个包装类,通过构造函数注入Car实例,对包装类进行切面

public class CarWrapper implements Car {

    private Car car;

    //构造方法注入实例
    public CarWrapper(Car car){
        System.out.println("init car wrapper");
        this.car=car;
    }

    //重写getColor方法对其进行切面操作
    @Override
    public void getColor() {
        System.out.println("==========before aop===========");
        car.getColor();
        System.out.println("==========after aop===========");
    }
}

@Adaptive 实现接口自适应机制。 优先级 类>接口>方法。

new ExtensionLoader<T>(Class<?> type)

private ExtensionLoader(Class<?> type) {
    this.type = type;
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

扩展工厂扩展接口,扩展类都要实现

@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

Dubbo默认使用 SPI扩展工厂

public class SpiExtensionFactory implements ExtensionFactory {

    @Override
    public <T> T getExtension(Class<T> type, String name) {
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
            if (!loader.getSupportedExtensions().isEmpty()) {
                //调用了自适应扩展
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }

}

自适应扩展工厂,匹配dubbo spi扩展机制

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    //扩展对象的集合,默认的可以分为dubbo 的SPI中接口实现类对象或者Spring bean对象
    private final List<ExtensionFactory> factories;

    //构造函数 加载自适应实例对象
    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);
    }

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

}

Spring扩展工厂

public class SpringExtensionFactory implements ExtensionFactory {
    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);
    
    private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();

    public static void addApplicationContext(ApplicationContext context) {
        CONTEXTS.add(context);
        if (context instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext) context).registerShutdownHook();
        }
    }
    
    public static void removeApplicationContext(ApplicationContext context) {
        CONTEXTS.remove(context);
    }

    public static Set<ApplicationContext> getContexts() {
        return CONTEXTS;
    }

    // currently for test purpose
    public static void clearContexts() {
        CONTEXTS.clear();
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getExtension(Class<T> type, String name) {

        //判断如果是接口 并且加了@SPI注解 返回null。是spi应该调SpiExtensionFactory
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            return null;
        }
        //判断spring容器中是否存在这样一个bean 有就返回没有就返回null
        for (ApplicationContext context : CONTEXTS) {
            T bean = BeanFactoryUtils.getOptionalBean(context, name, type);
            if (bean != null) {
                return bean;
            }
        }

        //logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName());

        return null;
    }
}

Dubbo SPI 工作原理

案例

public static void main(String[] args) {
    ExtensionLoader<Car> extensionLoader =  ExtensionLoader.getExtensionLoader(Car.class);

    Car redCar = extensionLoader.getExtension("red");
    redCar.getColor();


    Car greeCar = extensionLoader.getExtension("gree");
    Map<String, String> map = new HashMap<>();
    map.put("car","black");
    URL url = new URL("","",1,map);
    greeCar.getColorForUrl(url);
    greeCar.getColor();

    try {
        System.in.read();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

ExtensionLoader 加载器

先获取Car类型的加载器

ExtensionLoader<Car> extensionLoader =  ExtensionLoader.getExtensionLoader(Car.class);

在Dubbo中每一个SPI扩展接口都有自己的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!");
    }
    //必须有@SPI注解
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type (" + type +
                ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
    }

    //从EXTENSION_LOADERS(ConcurrentMap<Class<?>,ExtensionLoader<?>>)缓存中查询是否映存在对应的ExtensionLoader
    ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    if (loader == null) {
        //不存在就new一个并放缓存里
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
        loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    }
    //返回接口锁对应的ExtensionLoader实例
    return loader;
}

从META-INF/service/ 中读取com.marx.dubbo_spi.api.Car配置文件

red = com.nx.samuel.dubbo_spi.impl.RedCar

根据key读取配置加载实例

Car redCar = extensionLoader.getExtension("red");

加载实例代码逻辑

public T getExtension(String name) {
    return getExtension(name, true);
}
/**
 * 扩展实例缓存
 * key = 扩展点名称
 * value = 扩展实例的包装好的Holder实例(实例里有这个扩展点实例的实际对象)
 * @param name
 * @param wrap
 * @return
 */
public T getExtension(String name, boolean wrap) {
    if (StringUtils.isEmpty(name)) {
        throw new IllegalArgumentException("Extension name == null");
    }
    //扩展点名称是true 那么返回默认的扩展类
    if ("true".equals(name)) {
        return getDefaultExtension();
    }
    //扩展实例缓存容器,从缓存中获取,没有就创建一个放入缓存中
    final Holder<Object> holder = getOrCreateHolder(name);
    ......
}

getOrCreateHolder(name) 根据扩展名,从cachedInstances(ConcurrentMap<String, Holder<Object>>)中获取扩展实例对象,获取到了则直接返回

/**
 * 获取活创建一个Holder对象
 * @param name
 * @return
 */
private Holder<Object> getOrCreateHolder(String name) {
    //通过扩展名从扩展实例缓存中获取holder对象
    Holder<Object> holder = cachedInstances.get(name);
    if (holder == null) {
        cachedInstances.putIfAbsent(name, new Holder<>());
        holder = cachedInstances.get(name);
    }
    return holder;
}

调用getOrCreateHolder 如果没有获取到 则继续执行代码

public T getExtension(String name, boolean wrap) {
    if (StringUtils.isEmpty(name)) {
        throw new IllegalArgumentException("Extension name == null");
    }
    //扩展点名称是true 那么返回默认的扩展类
    if ("true".equals(name)) {
        return getDefaultExtension();
    }
    //扩展实例缓存容器,从缓存中获取,没有就创建一个放入缓存中
    final Holder<Object> holder = getOrCreateHolder(name);
    Object instance = holder.get();
    //DCL
    if (instance == null) {
        synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
                //创建扩展点实例
                instance = createExtension(name, wrap);
                //放入缓存
                holder.set(instance);
            }
        }
    }
    return (T) instance;
}

如果instance == null 即 还是没有获取到扩展点实例对象,则调用 createExtension 创建实例,并放入缓存中

/**
 * 根据扩展名加载扩展类对应的class对象
 * @param name
 * @param wrap
 * @return
 */
@SuppressWarnings("unchecked")
private T createExtension(String name, boolean wrap) {
    //从缓存中获取扩展类对象 
    Class<?> clazz = getExtensionClasses().get(name);
    //没有获取到就抛出异常
    if (clazz == null) {
        throw findException(name);
    }
     // 获取到了类对象继续执行
    try {
        //根据clazz对象,从扩展点实例缓存中获取对应的实例对象
        T instance = (T) EXTENSION_INSTANCES.get(clazz);
        if (instance == null) {
            //如果通过扩展类对象还是没有获取到扩展实例 则通过扩展类创建一个实例放入缓存中
            EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
            instance = (T) EXTENSION_INSTANCES.get(clazz);
        }

        //实现依赖注入,通过setter方法自动注入对应的属性实例
        injectExtension(instance);


        //自动注入缓存中的所有包装类
        if (wrap) {

            List<Class<?>> wrapperClassesList = new ArrayList<>();
            if (cachedWrapperClasses != null) {
                wrapperClassesList.addAll(cachedWrapperClasses);
                wrapperClassesList.sort(WrapperComparator.COMPARATOR);
                Collections.reverse(wrapperClassesList);
            }

            if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
                for (Class<?> wrapperClass : wrapperClassesList) {
                    Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
                    if (wrapper == null
                            || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
                        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                    }
                }
            }
        }

        //初始化实例并返回
        initExtension(instance);
        return instance;
    } catch (Throwable t) {
        throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                type + ") couldn't be instantiated: " + t.getMessage(), t);
    }
}

getExtensionClasses 获取所有的扩展类 cachedClasses (Holder<Map<String, Class<?>>>)

/**
 * 加载扩展点对应的类
 * 从缓存中获取所有的扩展点的类,如果没有就重新扫描一次,并缓存起来
 * key:扩展名
 * value:对应的class对象
 * @return
 */
private Map<String, Class<?>> getExtensionClasses() {
    //1、从缓存中获取出已经缓存的扩展点的classs
    Map<String, Class<?>> classes = cachedClasses.get();
    if (classes == null) {
        //如果没有缓存过,那么就根据配置扫描
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                //扫描配置文件,加载配置的扩展点的class
                classes = loadExtensionClasses();
                //将稻苗到的class存入到缓存
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}

loadExtensionClasses 扫描配置 加载配置扩展实现类,Map<String,Class<?>> extensionClasses ,key对应配置文件的扩展名,value对应配置文件的类全名

private Map<String, Class<?>> loadExtensionClasses() {
    /**
     * 获取注解了SPI的接口中指定的默认的实现类的名称
     * 存入到内存缓存中
     * 接口没有标注@SPI或者标注了@SPI注解但是没有指定默认实现类的名称时不做任务的处理
     */
    cacheDefaultExtensionName();

    Map<String, Class<?>> extensionClasses = new HashMap<>();
    // 遍历加载策略
    for (LoadingStrategy strategy : strategies) {
        loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
        loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    }

    return extensionClasses;
}

加载策略 LoadingStrategy [ ] strategies

private static LoadingStrategy[] loadLoadingStrategies() {
    return stream(load(LoadingStrategy.class).spliterator(), false)
            .sorted()
            .toArray(LoadingStrategy[]::new);
}

load方法 调用类加载器加载了 LoadingStrategy.class,LoadingStrategy 有4种实现

image.png

  • Dubbo 外部加载策略 DubboExternalLoadingStrategy,优先级 MAX_PRIORITY + 1,加载目录 META-INF/dubbo/external/

  • Dubbo 内部加载策略,DubboInternalLoadingStrategy, 优先级 MAX_PRIORITY (Integer最小值), 加载目录 META-INF/dubbo/internal/

  • Dubbo 一般加载策略,DubboLoadingStrategy,优先级 NORMAL_PRIORITY (0),加载目录 META-INF/dubbo/

  • SPI默认加载策略,ServicesLoadingStrategy,优先级 MIN_PRIORITY (Integer最大值),加载目录 META-INF/dubbo/services/

循环调用 loadDirectory 加载目录,获取到配置文件 URL

private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                           boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
    //配置文件的全路径:默认路径前缀+接口的全限定名
    String fileName = dir + type;
    try {
        Enumeration<java.net.URL> urls = null;
        // 获取当前线程的类加载器
        ClassLoader classLoader = findClassLoader();

        // try to load from ExtensionLoader's ClassLoader first
        if (extensionLoaderClassLoaderFirst) {
            //获取加载ExtenstionLoader.calss这个类的类加载器
            ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
            if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
                //如果两个类加载器不同,就默认使用extensionLoaderClassLoader
                urls = extensionLoaderClassLoader.getResources(fileName);
            }
        }

        if (urls == null || !urls.hasMoreElements()) {
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
        }

        if (urls != null) {
            //解析并加载配置文件中配置的实现类到extensionClasses缓存中
            while (urls.hasMoreElements()) {
                java.net.URL resourceURL = urls.nextElement();
                loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
            }
        }
    } catch (Throwable t) {
        logger.error("Exception occurred when loading extension class (interface: " +
                type + ", description file: " + fileName + ").", t);
    }
}

根据 URL解析配置文件,使用Class.forName加载类,并调用 loadClass

private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
                          java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
    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();
                        }
                        if (line.length() > 0 && !isExcluded(line, excludedPackages)) {

                            /**
                             *  加载配置的class到extensionClasses,使用Class.forName方式加载class
                             *  loadClass方法加载口哦站点的实现的class,这个方法的主要作用是对解析的class进行分类缓存
                             */

                            loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden);
                        }
                    } 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);
    }
}

调用loadClass进行分类缓存, 如果是Wrapper 包装类缓存到cacheWrapperClass,如果是配置@Adaptive 缓存到cacheAdaptiveClass中,如果都不是则判断是不是加了@Activate注解,缓存extensionClasses

private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
                       boolean overridden) throws NoSuchMethodException {
    //判断实现类是否显现了type接口
    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.");
    }
    //1、如果配置了@Adaptive注解,表示这是一个自适应类,缓存到cacheAdaptiveClass中
    if (clazz.isAnnotationPresent(Adaptive.class)) {
        cacheAdaptiveClass(clazz, overridden);
    } else if (isWrapperClass(clazz)) {
        //2、如果是一个wapper类就缓存到cacheWrapperClass中
        cacheWrapperClass(clazz);
    } else {
        //这里相当于校验类中是否存在默认的构造函数 如果不存在就抛出异常了
        clazz.getConstructor();
        if (StringUtils.isEmpty(name)) {//配置文件没有指定XX=com.。。。。中的XX这种已经启用了,不看了
            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)) {
            //3、如果扩展点配置的实现类使用的@Activate注解,就讲对应的注解信息缓存
            cacheActivateClass(clazz, names[0]);
            for (String n : names) {
                cacheName(clazz, n);// 缓存扩展点实现类的class和扩展点名称的对应关系
                saveInExtensionClass(extensionClasses, clazz, n, overridden);//将class存入到extensionClasses中
            }
        }
    }
}

injectExtension 实现依赖项注入。获取所有类的setter方法。 1.如果setter方法不是私有的和基础数据类型 并且没有@DisableInject注解来注解这个setter方法,就自动给相关属性注入默认的实现类 2.如果setter方法属性是一个接口,并且这个接口有多个实现类,则会增加@Adaptive注解 自适应加载配置的默认实现

/**
 * 这里实现了IOC和AOP
 * 获取类的所有的setter方法
 * @param instance
 * @return
 */
private T injectExtension(T instance) {

    /**
     * objectFactory为空的话就不属性注入了
     * objectFactory 是ExtensionFactory实例:从Dubbo容器和Spring容器中获取setter属性的默认扩展实例
     */

    if (objectFactory == null) {
        return instance;
    }

    try {
        for (Method method : instance.getClass().getMethods()) {
            //不是setter就不管了,条件1、public 2、set开头 3、只有一个参数
            if (!isSetter(method)) {
                continue;
            }
            /**
             * Check {@link DisableInject} to see if we need auto injection for this property
             */
            //setter方法加了DisableInject注解就不管了
            if (method.getAnnotation(DisableInject.class) != null) {
                continue;
            }

            Class<?> pt = method.getParameterTypes()[0];
            //级别数据类型也不管了
            if (ReflectUtils.isPrimitives(pt)) {
                continue;
            }

            try {
                //获取setter方法的属性值
                String property = getSetterProperty(method);

                Object object = objectFactory.getExtension(pt, property);
                if (object != null) {
                    //获取到属性的实例后,调用setter方法为该成员赋值
                    method.invoke(instance, object);
                }
            } catch (Exception e) {
                logger.error("Failed to inject via method " + method.getName()
                        + " of interface " + type.getName() + ": " + e.getMessage(), e);
            }

        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}

objectFactory 是 ExtensionLoader 中的实例变量,下面是ExtensionLoader的有参构造函数。 判断了如果参数类型不是 ExtensionFactory,则调用 getExtensionLoader 加载 ExtensionFactory 调用了自适应实例。

private ExtensionLoader(Class<?> type) {
    this.type = type;
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

初始化实例,初始化声明周期

private void initExtension(T instance) {
    if (instance instanceof Lifecycle) {
        Lifecycle lifecycle = (Lifecycle) instance;
        lifecycle.initialize();
    }
}

将配置中心ConfigCenter的信息存入到本地缓存中

public void initialize() throws IllegalStateException {
    ConfigManager configManager = ApplicationModel.getConfigManager();
    Optional<Collection<ConfigCenterConfig>> defaultConfigs = configManager.getDefaultConfigCenter();
    defaultConfigs.ifPresent(configs -> {
        for (ConfigCenterConfig config : configs) {
            this.setExternalConfigMap(config.getExternalConfiguration());
            this.setAppExternalConfigMap(config.getAppExternalConfiguration());
        }
    });

    this.externalConfiguration.setProperties(externalConfigurationMap);
    this.appExternalConfiguration.setProperties(appExternalConfigurationMap);
}

ExtensionLoader.getExtension(String name) 完整流程图

image.png

xml解析暴露 dubbo:service过程

Dubbo项目中 dubbo-config模块下的config-spring中有一个dubbo.xsd配置文件。

image.png

在这个配置文件中配置了dubbo的文件约束。

xml解析配置文件 spring.handlers中配置了Dubbo解析xml的处理器

http://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
http://code.alibabatech.com/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler

DubboNamespaceHandler 处理器重写了父类的两个方法init和parse。parse主要做解析配置操作,init完成了初始化Beandefinision

image.png

public class DubboNamespaceHandler extends NamespaceHandlerSupport implements ConfigurableSourceBeanMetadataElement {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    @Override
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
        registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
        registerBeanDefinitionParser("ssl", new DubboBeanDefinitionParser(SslConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

  
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        BeanDefinitionRegistry registry = parserContext.getRegistry();
        //注册注解驱动处理器
        registerAnnotationConfigProcessors(registry);
        
        //注册为普通的bean
        registerCommonBeans(registry);
        //parse 解析标签
        BeanDefinition beanDefinition = super.parse(element, parserContext);
        setSource(beanDefinition);
        return beanDefinition;
    }

    //注册注解驱动处理器
    private void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(registry);
    }
}

DubboBeanUtils.registerCommonBeans

static void registerCommonBeans(BeanDefinitionRegistry registry) {

    // 注册加了@Reference注解的bean, ReferenceAnnotationBeanPostProcessor
    registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
            ReferenceAnnotationBeanPostProcessor.class);

     //注册别名配置处理处理器 DubboConfigAliasPostProcessor
    registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
            DubboConfigAliasPostProcessor.class);

    //重点看这个方法,注册基础Bean,Dubbo应用的注册事件监听器
    registerInfrastructureBean(registry, DubboApplicationListenerRegistrar.BEAN_NAME,
            DubboApplicationListenerRegistrar.class);

    // Dubbo配置文件属性处理器 PropertyValueBeanPostProcessor
    registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
            DubboConfigDefaultPropertyValueBeanPostProcessor.class);
 
    // Dubbo 配置服务提前暴露 EarlyInitializationPostProcessor
    registerInfrastructureBean(registry, DubboConfigEarlyInitializationPostProcessor.BEAN_NAME,
            DubboConfigEarlyInitializationPostProcessor.class);
}

DubboApplicationListenerRegistrar.class 实现了ApplicationContextAware接口,将会在Spring容器初始化之后调用setApplicationContext方法,可以获取到Spring容器的上下文进行操作

public class DubboApplicationListenerRegistrar implements ApplicationContextAware {

    public static final String BEAN_NAME = "dubboApplicationListenerRegister";

    /**
     * 实现了ApplicationContextAware接口的类会被调用setApplicationContext方法,从而获取到spring容器的上下文
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (!isAssignable(ConfigurableApplicationContext.class, applicationContext.getClass())) {
            throw new IllegalArgumentException("The argument of ApplicationContext must be ConfigurableApplicationContext");
        }
        //添加应用监听器
        addApplicationListeners((ConfigurableApplicationContext) applicationContext);
    }

    private void addApplicationListeners(ConfigurableApplicationContext context) {
        //添加监听context.refresh事件的监听器,主要是为了服务注册和服务暴露
        context.addApplicationListener(createDubboBootstrapApplicationListener(context));
        //添加Dubbo生命周期的监听器
        context.addApplicationListener(createDubboLifecycleComponentApplicationListener(context));
    }

    private ApplicationListener<?> createDubboBootstrapApplicationListener(ConfigurableApplicationContext context) {
        return new DubboBootstrapApplicationListener(context);
    }

    private ApplicationListener<?> createDubboLifecycleComponentApplicationListener(ConfigurableApplicationContext context) {
        return new DubboLifecycleComponentApplicationListener(context);
    }
}

在Spring中添加了监听器DubboBootstrapApplicationListener

public class DubboBootstrapApplicationListener extends OnceApplicationContextEventListener implements Ordered {

    public static final String BEAN_NAME = "dubboBootstrapApplicationListener";

    private final DubboBootstrap dubboBootstrap;

    //监听器构造方法中实例化DubboBootstrap实例
    public DubboBootstrapApplicationListener(ApplicationContext applicationContext) {
        super(applicationContext);
        this.dubboBootstrap = DubboBootstrap.getInstance();
    }

    @Override
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            //如果是spring容器刷新事件,就启动dubbo服务
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            //如果是spring容器关闭事件,就停止dubbo服务
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }
    
    private void onContextRefreshedEvent(ContextRefreshedEvent event) {
        dubboBootstrap.start();
    }

    private void onContextClosedEvent(ContextClosedEvent event) {
        dubboBootstrap.stop();
    }

    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }
}

Dubbo启动,核心就做2件事。 1.初始化 2.暴露服务

public DubboBootstrap start() {
    //1. 判断是不是没有启动,如果是就将true设置给started表示,然后执行启动程序
    if (started.compareAndSet(false, true)) {
        ready.set(false);
        //2. 初始化
        initialize();
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " is starting...");
        }
        // 3. export Dubbo Services 暴露Provider的 Services
        exportServices();

        // Not only provider register
        if (!isOnlyRegisterProvider() || hasExportedServices()) {
            // 4.导出元数据 export MetadataService
            exportMetadataService();
            //5. Register the local ServiceInstance if required通过spi方式获取服务注册中心
            registerServiceInstance();
        }
            //6 处理Consumer的ReferenceConfig
        referServices();
        if (asyncExportingFutures.size() > 0) {//异步操作,在exportServices中添加
            new Thread(() -> {
                try {
                    this.awaitFinish();
                } catch (Exception e) {
                    logger.warn(NAME + " exportAsync occurred an exception.");
                }
                ready.set(true);
                if (logger.isInfoEnabled()) {
                    logger.info(NAME + " is ready.");
                }
            }).start();
        } else {
            ready.set(true);
            if (logger.isInfoEnabled()) {
                logger.info(NAME + " is ready.");
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " has started.");
        }
    }
    return this;
}

未完待续...