SPI是Service provider Interface是一种进程级别的服务发现机制,通过配置来决定进程运行时具体使用接口的哪个实现类。
Dubbo SPI做了一些增强,增加了IOC和AOP的特性。
Dubbo对配置的文件目录分为三类:
1.meta-INF/services/目录,此目录下的SPI配置文件用于兼容Java SPI
2.meta-INF/dubbo/目录,此目录下的SPI配置文件为用户自定义的SPI配置文件
3.meta-INF/internal/目录,此目录下的SPI配置文件为Dubbo内部的SPI配置文件
Dubbo SPI和Java SPI的区别
Java SPI:在遍历SPI配置文件时会将全部实现类实例化,即使有些实现类用不到也会创建它的实例对象,有些类实例化如果执行耗时,会影响程序的启动速度。
Dubbo SPI:1)可以实例化所有的实现类,也可以只实例化指定的实现类;2)支持延迟加载;3)增加了IOC和AOP支持,一个扩张点还可以注入其他扩展点;4)Dubb SPI扩展还支持Spring IOC容器。
第2节 Dubbo SPI的实现实现Dubbo SPI核心类、接口和注解如下图
| 名称 | 类型 | 作用 |
| LoadingStrategy | 接口 | 定义从jar包内部加载SPI配置的具体的meta-INF 路径 |
| ExtensionFactory | 接口 | 在给SPI接口的类实例注入依赖时,通过ExtensionFactory工厂获取依赖的对象实例。 有三个实现类:AdaptiveExtensionFactory,SpringExtensionFactory,SpiExtensionFactory。 ExtensionFactory自身被@SPI注解修饰,也是通过ExtensionLoader加载和实例化。 |
| SPI | 注解 | Dubbo的SPI注解,带有SPI注解的接口才能用ExtensionLoader.getExtensionLoader()方法加载、实例化 |
| Adaptive | 注解 | 只有AdaptiveExtensionFactory类带有这个注解修饰,ExtensionLoader在加载ExtensionFactory实现类时会特别处理AdaptiveExtensionFactory类 |
| Active | 注解 | |
| DisableInject | 注解 | ExtensionLoader在向构建的新对象中注入依赖的其他对象时,对带有@DisableInject注解修饰的set方法对应的字段不进行注入 |
| Wrapper | 注解 | Dubbo的AOP增强注解 |
| ExtensionLoader | 类 | 从jar报内部的meta-INF资源目录读取SPI配置,加载实现类,缓存默认实现类名、类、实例等信息,构建SPI接口的实现类实例和注入依赖。ExtensionLoader构建的类都是单例。 |
| AdaptiveExtensionFactory | 类 | 内部聚合SpringExtensionFactory和SpiExtensionFactory两个对象,ExtensionLoader通过AdaptiveExtensionFactory获取依赖的对象,它再使用SpringExtensionFactory或者SpiExtensionFactory获取依赖的对象 |
| SpringExtensionFactory | 类 | 使用Spring容器构建bean对象 |
| SpiExtensionFactory | 类 | 使用Dubbo的SPI构建依赖的单例对象,最终也是通过ExtensionLoader构建对象 |
ExtensionLoader类的静态字段EXTENSION_LOADERS是一张映射表,用于保存每个SPI接口的ExtensionLoader加载器对象,这些加载器对象都是单例的(注意不是通过单例模式实现)。
public class ExtensionLoader{ private static final ConcurrentMap , ExtensionLoader>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64); private static final ConcurrentMap , Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64); }
通过调用ExtensionLoader的getExtensionLoader()静态方法获取一个SPI接口的ExtensionLoader加载器。
ExtensionLoader



