本质:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。
java SPI:用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。具体流程为:
- 需要在 classpath 下创建一个目录,该目录命名必须是:META-INF/service。
- 在该目录下创建一个 文本文件,该文件需要满足以下几个条件:文件名必须是扩展的接口的全路径名称、文件内部描述的是该扩展接口的所有实现类、文件的编码格式是 UTF-8。
- 通过 java.util.ServiceLoader 的加载机制来加载服务。
javaSPI我们最熟悉的应用就是数据库驱动了,mysql和oracle驱动针对JDBC分别有自己的实现,这就有赖于java的SPI机制。
JDK SPI 机制就存在以下一些问题:
- 实现类会被全部遍历并且实例化,假如我们只需要使用其中的一个实现,这在实现类很多的情况下无疑是对机器资源巨大的浪费。
- 无法按需获取实现类,不够灵活,我们需要遍历一遍所有实现类才能找到指定实现。
Dubbo SPI:在dubbo中也有SPI机制,虽然都需要将接口全限定名配置在文件中,但是dubbo并没有使用java的spi机制,而是重新实现了一套功能更强【支持AOP与依赖注入】的 SPI 机制,并且 利用缓存提高加载实现类的性能,同时支持实现类的灵活获取。基于SPI,我们可以很容易的对 Dubbo 进行拓展。例如dubbo当中的protocol,LoadBalance等都是通过SPI机制扩展。具体实现流程如下:
- 需要在 classpath 下创建一个目录,该目录命名可以是:META-INF/service/、META-INF/dubbo/、META-INF/dubbo/internal/。
- 在该目录下创建一个 文本文件,该文件需要满足以下几个条件:文件名必须是扩展的接口的全路径名称、文件内部描述的是该扩展接口的所有实现类,将服务实现类写成KV键值对的形式,Key是拓展类的name,Value是扩展的全限定名实现类。
- 通过 org.apache.dubbo.common.extension.ExtensionLoader 的加载机制来加载服务。
java SPI和dubbo SPI对比:
- Java SPI在加载扩展点的时候,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源。dubboSPI有选择性地加载所需要的SPI接口。
- javaSPI配置文件中只是简单的列出了所有的扩展实现,而没有给他们命名。导致在程序中很难去准确的引用它们。而dubboSPI配置文件中以键值对的形式有别名,易于区分。
- SPI扩展如果依赖其他的扩展,javaspi做不到自动注入和装配,dubbo可以实现自动注入。
- javaSPI不提供类似于Spring的IOC和AOP功能,dubboSPI是支持的。
Spring SPI机制之SpringFactoriesLoader约定如下:
- 配置文件必须在
META-INF/
目录下,文件名必须为spring.factories。 - 文件内容为键值对,一个键可以有多个值(逗号分割)。键和值都需要是类的全限定名,键和值可以没有任何类与类之间的关系,当然也可以有实现的关系。
// 这种方式对应的接口Driver以及配置的类可以不存在任何关系
List<String> stringList = SpringFactoriesLoader.loadFactoryNames(Driver.class, App.class.getClassLoader());
stringList.stream().forEach(item -> System.out.println(item));
// 这种方式配置的扩展类一定是接口Driver的实现类
List<Driver> drivers = SpringFactoriesLoader.loadFactories(Driver.class, App.class.getClassLoader());
如下所示:键值中值可以是任意包路径下的类。
net.csdn.spi.Driver=net.csdn.spi.Mysql,net.ali.Oracle
与Java SPI机制对比:
- 首先Spring的SPI机制对Java的SPI机制对进行了一些简化,Java的SPI每个接口都需要对应的文件,而Spring的SPI机制只需要一个spring.factories文件。
- Java的SPI机制文件内容必须为接口的实现类,而Spring的SPI并不要求键值对必须有什么关系,更加灵活。
- Spring的SPI机制提供了获取类限定名的方法
loadFactoryNames
,而Java的SPI机制是没有的。通过这个方法获取到类限定名之后就可以将这些类注入到Spring容器中,用Spring容器加载这些Bean,而不仅仅是通过反射。
Spring的SPI也同样没有实现获取指定某个指定实现类的功能,所以要想能够找到具体的某个实现类,还得依靠具体接口的设计。
所以不知道你有没有发现,PropertySourceLoader它其实就是一个策略接口,注释也有说,所以当你的配置文件是properties格式的时候,他可以找到解析properties格式的PropertiesPropertySourceLoader对象来解析配置文件。
1.ScopeModel
抽象这三个能力是为了实现 Dubbo 的多实例支持,FrameworkModel 是实现类似 JVM 租户级别的隔离,ApplicationModel 是为了实现一个机器上发布多个应用(如 demo-application1 和 demo-application2 一起发布),ModuleModel 是为了实现服务生命周期的独立管理(如一个 demo-application 可以由多个 Spring 容器共同提供)。
public abstract class ScopeModel implements ExtensionAccessor {
private final ScopeModel parent;
private final ExtensionScope scope;
private ExtensionDirector extensionDirector;
// 子类构造器中分别指定parent & scope
public ScopeModel(ScopeModel parent, ExtensionScope scope, boolean isInternal) {
this.parent = parent;
this.scope = scope;
this.internalScope = isInternal;
}
protected void initialize() {
this.extensionDirector = new ExtensionDirector(parent != null ? parent.getExtensionDirector() : null, scope, this);
this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
}
@Override
public ExtensionDirector getExtensionDirector() {
return extensionDirector;
}
}
相关子类初始化时机:
- @EnableDubbo注解通过import方式引入类DubboConfigConfigurationRegistrar、DubboComponentScanRegistrar。
- 接口ImportBeanDefinitionRegistrar子类核心方法内部通过类DubboSpringInitializer触发ScopeModel相关子类。并且将Dubbo应用上下文DubboSpringInitContext、ApplicationModel、ModuleModel都被Spring IOC托管。--【@EnableDubbo该注解核心功能】
- FrameworkModel构造器中初始化ApplicationModel,ApplicationModel构造器中初始化ModuleModel。
- FrameworkModel、ApplicationModel、ModuleModel三者之间并没有Java编程语法意义上的继承关系,但是是通过父类ScopeModel的parent属性建立父子关系。
- FrameworkModel的parent属性为null,ApplicationModel的parent属性为FrameworkModel,ModuleModel的parent属性为ApplicationModel。
类ExtensionDirector作用:子类加载扩展类就是利用该类得到类ExtensionLoader完成SPI功能的。
1.1.FrameworkModel
public class FrameworkModel extends ScopeModel {
public FrameworkModel() {
super(null, ExtensionScope.FRAMEWORK, false);
...
initialize();
}
@Override
protected void initialize() {
super.initialize();
TypeDefinitionBuilder.initBuilders(this);
serviceRepository = new FrameworkServiceRepository(this);
// 获取 ScopeModelInitializer 类型的扩展类
ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
for (ScopeModelInitializer initializer : initializers) {
initializer.initializeFrameworkModel(this);
}
// 将当前类作为 ApplicationModel 的父类
internalApplicationModel = new ApplicationModel(this, true);
internalApplicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig(internalApplicationModel, CommonConstants.DUBBO_INTERNAL_APPLICATION));
internalApplicationModel.setModelName(CommonConstants.DUBBO_INTERNAL_APPLICATION);
}
}
1.2.ApplicationModel
public class ApplicationModel extends ScopeModel {
public ApplicationModel(FrameworkModel frameworkModel, boolean isInternal) {
super(frameworkModel, ExtensionScope.APPLICATION, isInternal);
this.frameworkModel = frameworkModel;
frameworkModel.addApplication(this);
initialize();
}
@Override
protected void initialize() {
super.initialize();
// 将当前类作为 ModuleModel 的父类
internalModule = new ModuleModel(this, true);
this.serviceRepository = new ServiceRepository(this);
// 加载 ApplicationInitListener类型 的扩展类
ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
Set<String> listenerNames = extensionLoader.getSupportedExtensions();
for (String listenerName : listenerNames) {
extensionLoader.getExtension(listenerName).init();
}
initApplicationExts();
// 加载 ScopeModelInitializer类型的 扩展类
ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
for (ScopeModelInitializer initializer : initializers) {
// 马上执行扩展类的核心方法
initializer.initializeApplicationModel(this);
}
}
}
1.3.ModuleModel
public class ModuleModel extends ScopeModel {
public ModuleModel(ApplicationModel applicationModel, boolean isInternal) {
super(applicationModel, ExtensionScope.MODULE, isInternal);
this.applicationModel = applicationModel;
applicationModel.addModule(this, isInternal);
initialize();
}
@Override
protected void initialize() {
super.initialize();
this.serviceRepository = new ModuleServiceRepository(this);
this.moduleConfigManager = new ModuleConfigManager(this);
this.moduleConfigManager.initialize();
initModuleExt();
// 加载 ScopeModelInitializer类型的扩展类
ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
for (ScopeModelInitializer initializer : initializers) {
// 马上执行扩展类的核心方法
initializer.initializeModuleModel(this);
}
}
}
2.ExtensionAccessor
利用Spi机制获取扩展类都是通过当前类先获取ExtensionLoader,后续通过ExtensionLoader加载对应的扩展类。
获取ExtensionLoader存在两种方式:
- 通过ExtensionDirector直接获取。
- 通过ExtensionAccessor间接获取。这种方式其实是通过ScopeModel间接获取到ExtensionDirector,其目的是利用ScopeModel初始化ExtensionDirector的parent属性。
如果是通过 ScopeModel 的子类获取扩展类,则必然是通过第二种方式获取ExtensionLoader。
public interface ExtensionAccessor {
// 由 ExtensionDirector 以及 ScopeModel 类实现该方法
ExtensionDirector getExtensionDirector();
default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
return this.getExtensionDirector().getExtensionLoader(type);
}
//支持获取特定name对应的扩展类
default <T> T getExtension(Class<T> type, String name) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getExtension(name) : null;
}
default <T> T getAdaptiveExtension(Class<T> type) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null;
}
default <T> T getDefaultExtension(Class<T> type) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
}
}
内部方法参数type类型必须是被@SPI注解的类。
FrameworkModel、ApplicationModel、ModuleModel三者抽象父类ScopeModel实现了方法:
public interface ExtensionAccessor {
ExtensionDirector getExtensionDirector();
}
2.1.ExtensionDirector
ExtensionDirector的作用其实就是获取扩展类的加载器ExtensionLoader。其实任何方式得到的扩展类的加载器都是ExtensionLoader,唯一的区别就是parent属性赋值与否。
ExtensionScope的取值涉及:FRAMEWORK、APPLICATION、MODULE、SELF。
public class ExtensionDirector implements ExtensionAccessor {
private final ConcurrentMap<Class<?>, ExtensionLoader<?>> extensionLoadersMap = new ConcurrentHashMap<>(64);
private final ConcurrentMap<Class<?>, ExtensionScope> extensionScopeMap = new ConcurrentHashMap<>(64);
public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
...
// 1. find in local cache
ExtensionLoader<T> loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
ExtensionScope scope = extensionScopeMap.get(type);
if (scope == null) {
SPI annotation = type.getAnnotation(SPI.class);
scope = annotation.scope();
extensionScopeMap.put(type, scope);
}
// 如果 type 的scope范围是SELF,则直接返回 ExtensionLoader,并不需要考虑 属性parent的功能
if (loader == null && scope == ExtensionScope.SELF) {
// create an instance in self scope
loader = createExtensionLoader0(type);
}
// 2. find in parent
if (loader == null) {
// 条件成立的条件是:必须是通过ScopeModel子类触发的扩展类加载
if (this.parent != null) {
// 递归的方式
loader = this.parent.getExtensionLoader(type);
}
}
// 3. create it
if (loader == null) {
// type & ScopeModel 的scope值必须匹配
loader = createExtensionLoader(type);
}
return loader;
}
private <T> ExtensionLoader<T> createExtensionLoader(Class<T> type) {
ExtensionLoader<T> loader = null;
if (isScopeMatched(type)) {
// if scope is matched, just create it
loader = createExtensionLoader0(type);
} else {
// if scope is not matched, ignore it
}
return loader;
}
private <T> ExtensionLoader<T> createExtensionLoader0(Class<T> type) {
checkDestroyed();
ExtensionLoader<T> loader;
extensionLoadersMap.putIfAbsent(type, new ExtensionLoader<T>(type, this, scopeModel));
loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
return loader;
}
private boolean isScopeMatched(Class<?> type) {
// 当前ScopeModel对应的scope值是否与type spi注解中scope一致
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
return defaultAnnotation.scope().equals(scope);
}
}
上述获取扩展类loader类似于jdk类加载器流程:
- 抽象类ScopeModel三个子类存在非Java规范意义上的继承关系。
- 任何一个ScopeModel的子类触发的loader流程优先获取属性parent的ExtensionLoader。
- 目标接口type注解SPI其scope属性必须与当前ScopeModel的scope值一致方能引用当前parent的ExtensionLoader。否则继续向下寻找child对应的ExtensionLoader。
- type的scope以及type的ExtensionLoader都存在集合类型的本地缓存。
扩展类loader加载机制的作用:不同child需要相同的扩展类,只要scope值一样则可以由parent统一触发,避免child多次触发;child定制化的扩展类则通过scope值单独实现。
2.2.ExtensionLoader
利用ExtensionLoader获取目标接口扩展类的方式:
-
普通SPI实现原理:指定name获取接口的扩展类。根据接口名找到并解析配置文件,加载对应的扩展点实现类;类加载成功后就可以反射创建对象;对该对象完成IOC及AOP。
-
自适应SPI(Adaptive注解)实现原理:Javaassit 编译器对目标接口生成代理。代理类【type$Adaptive】执行@Adaptive方法触发目标方法执行。
2.2.1.普通SPI实现原理
public class ExtensionLoader<T> {
private T createExtension(String name, boolean wrap) {
//执行核心方法:利用不同策略获取扩展候选类类
// 此处其实已经通过name得到候选类,例如利用javassist得到JavassistProxyFactory
Class<?> clazz = getExtensionClasses().get(name);
T instance = (T) extensionInstances.get(clazz);
if (instance == null) {
extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
// 反射创建候选类实例
instance = (T) extensionInstances.get(clazz);
...
}
if (wrap) {// 如果集合属性 cachedWrapperClasses 不为null,则需要通过代理方式增强目标方法功能,真正增强是通过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);
...
//如果 cachedWrapperClasses 集合中存在当前type对应的候选类,则依次返回wrapper类型的候选类
// 实例化wrapperClass:1.获取存在type构造参数的构造器;2.将type接口类型的实现子类通过构造方法属性赋值
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
}
...
return instance;
}
}
2.2.1.1.IOC
场景:SPI接口中通过set开头的方法注入其他SPI接口作为属性。
- set方法注入条件:set开头,参数只有一个并且public修饰。
- set方法上没有使用 DisableInject 注解。
- set 方法是在ScopeModelAware 系列中声明的也不能注入。
private T createExtension(String name, boolean wrap) {
// 1️⃣.加载扩展点实现类,得到class对象
Class<?> clazz = getExtensionClasses().get(name);
// 2️⃣.这里通过反射调用空参构造函数,完成实例化
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 3️⃣.IOC
injectExtension(instance);
// 4️⃣.AOP
if (wrap) {
// .....
}
// 5️⃣.扩展点生命周期,进一步完成初始化
initExtension(instance);
return instance;
}
public class ExtensionLoader<T> {
private final ExtensionInjector injector;
private T injectExtension(T instance) {
if (injector == null) {
return instance;
}
// 遍历 当前SPI接口存在的全部方法
for (Method method : instance.getClass().getMethods()) {
if (!isSetter(method)) {// 如果方法不存在set方法,则表明不存在IOC注入功能
continue;
}
//如果方法存在DisableInject注解,则表明不存在IOC注入功能
if (method.isAnnotationPresent(DisableInject.class)) {
continue;
}
// "set"方法只存在一个SPI接口类型的变量
Class<?> pt = method.getParameterTypes()[0];
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
// 从"set"方法名中获取 SPI接口 的名,例如setProtocol,表明SPI接口名为protocol
String property = getSetterProperty(method);
// 从 Dubbo IOC容器中 获取 beanName 为 property的 bean
Object object = injector.getInstance(pt, property);
if (object != null) {// 通过反射调用注入目标bean
method.invoke(instance, object);
}
}
return instance;
}
}
2.2.1.2.AOP
实现AOP功能的前提条件:
- SPI接口的实现类至少存在两个扩展类,一个是原始类,另一个是对原始类增强的wrappr类。
- wrappr类的类名最好以wrappr作为前缀。
- wrappr类存在有参构造方法,并且参数类型SPI接口类型,有且仅有一个参数。
- wrappr类中目标方法是增强方法。
public class ExtensionLoader<T> {
//增强之前,必须存在SPI接口的扩展类
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null || unacceptableExceptions.contains(name)) {
throw findException(name);
}
...
if (wrap) {
// SPI接口的扩展类必须同时存在wrapper类型的扩展类,用于增强目标类
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);
boolean match = (wrapper == null) ||
((ArrayUtils.isEmpty(wrapper.matches()) || ArrayUtils.contains(wrapper.matches(), name)) &&
!ArrayUtils.contains(wrapper.mismatches(), name));
if (match) {
// 此处就是对 增强类的实例化,注意:反射方式实例化时构造器必须在SPI接口类型的参数。
// 返回的实例也是SPI接口的扩展类,只不过该扩展类内部通过 SPI接口 回调了目标方法
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
instance = postProcessAfterInitialization(instance, name);
}
}
}
}
return instance;
}
2.2.2.自适应SPI(Adaptive注解)实现原理
Adaptive 机制可以指定想要加载的扩展名,也可以不指定。若不指定则直接加载默认的扩展类。即其会自动匹配做到自适应。其是通过@Adaptive
注解实现的。
该SPI机制的前提:
- 目标接口必须存在@Adaptive方法。
- @Adaptive方法首个参数必须是org.apache.dubbo.common.URL类型。
public class ExtensionLoader<T> {
private final Class<?> type;//目标接口
private Class<?> createAdaptiveExtensionClass() {
ClassLoader classLoader = type.getClassLoader();
// 目标接口type对应的代理类字符串形式
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
org.apache.dubbo.common.compiler.Compiler compiler = extensionDirector.getExtensionLoader(
org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(type, code, classLoader);
}
}
如上所示自适应SPI原理其实就是对目标接口type进行Javaassit编译生成代理类,如下所示:
public class Order$Adaptive implements net.dubbo.provider.spi.adaptive.Order {
//非@Adaptive方法
public java.lang.String way() {
throw new UnsupportedOperationException("The method public abstract java.lang.String net.dubbo.provider.spi.adaptive.Order.way() of interface net.dubbo.provider.spi.adaptive.Order is not adaptive method!");
}
//@Adaptive方法
public java.lang.String pay(org.apache.dubbo.common.URL arg0) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg0;
// order:目标接口名。wechat:接口@SPI指定的扩展类名。
// 从 URL 中获取 order 的value,默认值 @SPI指定的扩展类名
String extName = url.getParameter("order", "wechat");
if (extName == null)throw new IllegalStateException("Failed to get extension (net.dubbo.provider.spi.adaptive.Order) name from url (" + url.toString() + ") use keys([order])");
ScopeModel scopeModel = ScopeModelUtil.getOrDefault(url.getScopeModel(), net.dubbo.provider.spi.adaptive.Order.class);
// 通过 普通SPI 机制获取目标接口利用 @SPI注解指定的扩展类
Order extension = (Order) scopeModel.getExtensionLoader(Order.class).getExtension(extName);
return extension.pay(arg0);
}
}
所以综上所述,通过在代理类调用目标方法时可以改变 @SPI注解指定的扩展类名。
非@Adaptive方法通过代理类执行目标方法就直接抛出异常
2.3.LoadingStrategy
Dubbo SPI 的配置做出了改进,在 Dubbo 中有三种不同的目录可以存放 SPI 配置,用途也不同,优先级由低到高如下所示:
- META-INF/services/ 目录:此目录配置文件用于兼容 JDK SPI 【ServicesLoadingStrategy】。
- META-INF/dubbo/ 目录:此目录用于存放用户自定义 SPI 配置文件【DubboLoadingStrategy】。
- META-INF/dubbo/internal/ 目录:此目录用于存放 Dubbo 内部使用的 SPI 配置文件【DubboInternalLoadingStrategy】。
其中,只有ServicesLoadingStrategy在其对应目录文件中是不支持kv形式的。
3. ScopeModelInitializer
public interface ScopeModelInitializer {
void initializeFrameworkModel(FrameworkModel frameworkModel);
void initializeApplicationModel(ApplicationModel applicationModel);
void initializeModuleModel(ModuleModel moduleModel);
}
ScopeModelInitializer存在各种实现类,并且在ScopeModel子类的构造器中完成ScopeModelInitializer相关子类的实例化。其中ConfigScopeModelInitializer主要功能是完成接口Deployer子类的实例化。
4.ExtensionInjector
@SPI(scope = ExtensionScope.SELF)
public interface ExtensionInjector extends ExtensionAccessorAware {
@Override
default void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
}
}
该类型接口实现类:
- ScopeBeanExtensionInjector:从Dubbo自己设计的IOC容器中获取。
- SpringExtensionInjector:从Spring IOC容器中获取目标bean。
- SpiExtensionInjector:利用SPI机制加载注入的目标接口实现类。