零 后期筹备

0 FBI WARNING

文章异样啰嗦且绕弯。

1 版本

JDK 版本 : Adoptopenjdk 14.0.1
IDE : idea 2020.2
Dubbo 版本 : dubbo 2.7.6

2 Spi 简介

Dubbo Spi 是 Dubbo 框架扩展性的基本根底,是基于 jdk spi 的封装和扩大。

3 Demo

3.1 须要扩大的接口类

import org.apache.dubbo.common.extension.Adaptive;import org.apache.dubbo.common.extension.SPI;@SPI("dubbo")  // spi 最次要的注解public interface SpiDemoService {    void sayHello(); }

3.2 接口实现类

一号实现类 :

public class SpiDemoOneServiceImpl implements SpiDemoService {    @Override    public void sayHello() {        System.out.println("hello 1");    }}

二号实现类 :

public class SpiDemoTwoServiceImpl implements SpiDemoService {    @Override    public void sayHello() {        System.out.println("hello 2");    }}

测试方法类:

import org.apache.dubbo.common.extension.ExtensionLoader;public class SpiTest {    public static void main(String[] args) {        // 获取 loader 工厂类        ExtensionLoader<SpiDemoService> loader             = ExtensionLoader                .getExtensionLoader(SpiDemoService.class);        // 获取实体类        SpiDemoService one = loader.getExtension("one");        // 测试方法        one.sayHello();    }}

一 getExtensionLoader

回到 demo :

ExtensionLoader<SpiDemoService> loader             = ExtensionLoader                .getExtensionLoader(SpiDemoService.class);

1 getExtensionLoader

getExtensionLoader 是 ExtensionLoader 最外围的静态方法,用于获取 ExtensionLoader 实例

// org.apache.dubbo.common.extension.ExtensionLoaderpublic 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() + "!");        }        // 先尝试获取,如果获取失败就创立一个 ExtensionLoader        // EXTENSION_LOADERS 是一个动态 ConcurrentHashMap,用来寄存 loader        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);        if (loader == null) {            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);        }        return loader;    }

2 ExtensionLoader 结构器

// org.apache.dubbo.common.extension.ExtensionLoaderprivate ExtensionLoader(Class<?> type) {    // 存储要创立的 loader 的类型    this.type = type;        // objectFactory 是 ExtensionFactory 类型的对象,是用来依赖注入的工厂    objectFactory         = (type == ExtensionFactory.class ?           null : ExtensionLoader                     .getExtensionLoader(ExtensionFactory.class)                     .getAdaptiveExtension());    }

二 getAdaptiveExtension

1 getAdaptiveExtension

// org.apache.dubbo.common.extension.ExtensionLoaderpublic T getAdaptiveExtension() {    // cachedAdaptiveInstance 是一个 Holder 对象,Holder 是对 Object 的包装    // 在此处先尝试获取实例化实现的对象,如果获取不到,就进入加载逻辑    Object instance = cachedAdaptiveInstance.get();    if (instance == null) {            // 如果之前初始化的时候报错了,那么谬误会被记录下来并缓存在此处,间接抛出        // 此处的设计应该是缩小锁耗费        if (createAdaptiveInstanceError != null) {            throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(),            createAdaptiveInstanceError);        }        synchronized (cachedAdaptiveInstance) {            // 双锁验证            instance = cachedAdaptiveInstance.get();            if (instance == null) {                try {                    // 创立实例并存储在 Holder 对象里                    instance = createAdaptiveExtension();                    cachedAdaptiveInstance.set(instance);                } catch (Throwable t) {                    // 如果报错了就会把谬误存储起来                    createAdaptiveInstanceError = t;                    throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);                }            }        }    }        // 返回对象实例    return (T) instance;}

2 createAdaptiveExtension

创立实例对象:

// org.apache.dubbo.common.extension.ExtensionLoaderprivate T createAdaptiveExtension() {    try {        // getAdaptiveExtensionClass().newInstance() 办法会应用 Class 对象的 newInstance() 办法创立一个对象        // injectExtension(...) 则会对创立进去的对象进行依赖注入        return injectExtension((T)getAdaptiveExtensionClass().newInstance());    } catch (Exception e) {        throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);    }}

3 injectExtension

// org.apache.dubbo.common.extension.ExtensionLoaderprivate T injectExtension(T instance) {    // objectFactory 是用来依赖注入的 ExtensionFactory    // 如果 objectFactory 为空,就间接返回    // 须要留神的是,只有非 ExtensionFactory 的 loader 才有 objectFactory    if (objectFactory == null) {        return instance;    }    try {        // 轮训实例对象中所有的办法        for (Method method : instance.getClass().getMethods()) {                    // 如果办法不是 set 办法就跳过            // 此处能够了解为,dubbo 的 spi 依赖注入须要 set 办法反对            if (!isSetter(method)) {                continue;            }            // 如果办法被标注了 DisableInject 注解就跳过            if (method.getAnnotation(DisableInject.class) != null) {                continue;            }                        // 如果办法的参数是原始类型就跳过            // 依赖注入须要应用包装类型            Class<?> pt = method.getParameterTypes()[0];            if (ReflectUtils.isPrimitives(pt)) {                continue;            }            try {                            // 反射注入                String property = getSetterProperty(method);                Object object = objectFactory.getExtension(pt, property);                if (object != null) {                    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;}

三 ExtensionFactory

ExtensionFactory 是用来依赖注入的工厂:

@SPIpublic interface ExtensionFactory {    <T> T getExtension(Class<T> type, String name);}

该接口在 Dubbo 中有三个默认实现类:

org.apache.dubbo.config.spring.extension.SpringExtensionFactoryorg.apache.dubbo.common.extension.factory.AdaptiveExtensionFactoryorg.apache.dubbo.common.extension.factory.SpiExtensionFactory

在开发中 SpringExtensionFactory 应该会用的更宽泛一些,本示例中此处临时不开展。

1 AdaptiveExtensionFactory

AdaptiveExtensionFactory 是默认工厂:

import org.apache.dubbo.common.extension.Adaptive;import org.apache.dubbo.common.extension.ExtensionFactory;import org.apache.dubbo.common.extension.ExtensionLoader;import java.util.ArrayList;import java.util.Collections;import java.util.List;@Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {    private final List<ExtensionFactory> factories;    // 结构器    public AdaptiveExtensionFactory() {        ExtensionLoader<ExtensionFactory> loader             = ExtensionLoader                .getExtensionLoader(ExtensionFactory.class);                // AdaptiveExtensionFactory 会将 SpiExtensionFactory 和 SpringExtensionFactory 搁置在 factories 列表里                List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();        for (String name : loader.getSupportedExtensions()) {            list.add(loader.getExtension(name));        }        factories = Collections.unmodifiableList(list);    }    // 应用 AdaptiveExtensionFactory 去获取实体类的时候,    // 会调用 spi 或者 spring 的 ext 工厂去尝试获取实体类    @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;    }}

2 SpiExtensionFactory

import org.apache.dubbo.common.extension.ExtensionFactory;import org.apache.dubbo.common.extension.ExtensionLoader;import org.apache.dubbo.common.extension.SPI;public class SpiExtensionFactory implements ExtensionFactory {    @Override    public <T> T getExtension(Class<T> type, String name) {        // spi 工厂用于解析 spi 注解        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {            // 如果传入的 type 是一个被 spi 正文的接口,那么会初始化一个它的 class loader            ExtensionLoader<T> loader                     = ExtensionLoader.getExtensionLoader(type);                                // 初始化对象            if (!loader.getSupportedExtensions().isEmpty()) {                return loader.getAdaptiveExtension();            }        }        return null;    }}

四 getExtension

回到 demo :

SpiDemoService one = loader.getExtension("one");

1 getExtension

// org.apache.dubbo.common.extension.ExtensionLoaderpublic T getExtension(String name) {    // 非空验证,疏忽    if (StringUtils.isEmpty(name)) {        throw new IllegalArgumentException("Extension name == null");    }        // 默认机制,会去找名称为 dubbo 的实例    // 个别用不到    if ("true".equals(name)) {        return getDefaultExtension();    }        // 如果之前不存在这个名称对应的 Holder 对象,此处会创立一个空白的 Holder    // 调用 get() 办法会取得空对象    final Holder<Object> holder = getOrCreateHolder(name);    Object instance = holder.get();    if (instance == null) {        synchronized (holder) {            instance = holder.get();            if (instance == null) {                // 创建对象实例,并装进 holder 中                instance = createExtension(name);                holder.set(instance);            }        }    }    // 返回实例    return (T) instance;}

2 createExtension

// org.apache.dubbo.common.extension.ExtensionLoaderprivate T createExtension(String name) {    // 如果 class 不存在就报错    Class<?> clazz = getExtensionClasses().get(name);    if (clazz == null) {        throw findException(name);    }        try {        // 尝试获取 class 对应的实例,如果不存在就创立        T instance = (T) EXTENSION_INSTANCES.get(clazz);        if (instance == null) {            EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());            instance = (T) EXTENSION_INSTANCES.get(clazz);        }                // 进行依赖注入        injectExtension(instance);        Set<Class<?>> wrapperClasses = cachedWrapperClasses;        if (CollectionUtils.isNotEmpty(wrapperClasses)) {            for (Class<?> wrapperClass : wrapperClasses) {                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);    }}

五 一点唠叨

1 总结

spi 的代码有点绕,做一下总结。

ExtensionLoader

ExtensionLoader 是整个 spi 零碎的门面,也是 spi 的实例联合类。

内置对象

  • EXTENSION_LOADERS

记录了 class 和 loader 的对应关系

  • EXTENSION_INSTANCES

记录了 class 和实例对象的对应关系。能够认为是一个动态的全局 bean 容器。

次要办法

  • getExtensionLoader(Class)

尝试创立这个 class 对应的 loader 对象;
然而在创立个别 spi 接口的 loader 对象之前,还会先创立 ExtensionFactory 的 loader 对象。

  • getExtension(String)

依照需要实例化对象,搁置到 EXTENSION_INSTANCES 对象中,而后做依赖注入并返回给使用者。

ExtensionFactory

用来做依赖注入的工厂。
ExtensionFactory 也是被 ExtensionLoader 治理的一类非凡的 spi 类。

2 未实现

dubbo 的 spi 还有很重要的一部分即为 @Adaptive 注解的应用,这部分波及动静代理,较为简单,有空开新篇讲。


本文仅为集体的学习笔记,可能存在谬误或者表述不清的中央,有缘补充