dubbo SPI 实现原理
a).定义一个接口
b).实现一个接口
c).在 MATE-INF/dobbo 下创建以接口全限定名的文件名
d).文件内容为 key=实现类全限定名 例如: impl=chenyi.dubbo.test.dubbo.PrintInfoDubboServiceImpl
e).接口添加注解SPI(“impl”)SPI:是dubbo包下的。 impl是配置文件中的key
f).通过dubbo的方式获取对应扩展类: ExtensionLoader.getExtensionLoader(PrintInfoDubboService.class)
.getDefaultExtension();
接下来就通过获取对应扩展类的代码看看底层是怎么实现的:
//获取扩展加载类
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
} else if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
// 只接受@SPI注解的类
} else if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
} else {
//尝试从缓存中获取ExtensionLoader实力
ExtensionLoader<T> loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
if (loader == null) {
//根据类型 创建ExtensionLoader
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
}
return loader;
}
}
上述代码通过传入的Class 类型的参数.判断该类型必须是接口类型,而且是被==@SPI== 注解标识的接口,在获取ExtensionLoader 实例时,先从静态缓存中获取,如果没有,就执行 new ExtensionLoader(type) 创建新的类型
接下来看 new ExtensionLoader(type)
//ExtensionLoader 构造函数
private ExtensionLoader(Class<?> type) {
this.type = type;
//如果传入的类型是ExtensionFactory则返回为null,否则就调用getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
}
这里的 objectFactory 是一个ExtensionFactory 类型的属性. 如果该类型为null,则需要重新构建.
来看看 getExtensionLoader(ExtensionFactory.class) 方法的不就是刚开始我们进入的方法吗,来看下ExtensionFactory.class
可以看出来 ExtensionFactory 被@SPI 标注 而且对应的实现类 有 AdaptiveExtensionFactory 和 SpiExtensionFactory 以及 SpringExtensiionFactory
在所有的ExtensionFactory 实现类中,只有 AdaptiveExtensionFactory 被 @Adaptive标注, 标识是默认实现.
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
// 构造方法中,获取 ExtensionFactory 的 ExtensionLoader
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList();
// 将所有ExtensionFactory实现保存起来
Iterator var3 = loader.getSupportedExtensions().iterator();
while(var3.hasNext()) {
String name = (String)var3.next();
list.add(loader.getExtension(name));
}
this.factories = Collections.unmodifiableList(list);
}
//根据 类型 和名称获取
public <T> T getExtension(Class<T> type, String name) {
Iterator var3 = this.factories.iterator();
Object extension;
do {
if (!var3.hasNext()) {
return null;
}
// 依次遍历各个ExtensionFactory实现的getExtension方法,一旦获取到Extension即返回
// 如果遍历完所有的ExtensionFactory实现均无法找到Extension,则返回null
ExtensionFactory factory = (ExtensionFactory)var3.next();
extension = factory.getExtension(type, name);
} while(extension == null);
return extension;
}
}
AdaptiveExtensionFactory他会遍历当前系统中所有的ExtensionFactory实现来获取指定的扩展实现,获取到扩展实现或遍历完所有的ExtensionFactory实现。这里调用了ExtensionLoader的getSupportedExtensions方法来获取ExtensionFactory的所有实现,又回到了ExtensionLoader类
接下来看一下 getAdaptiveExtension() 的实现
//
public T getAdaptiveExtension() {
//private final Holder<Object> cachedAdaptiveInstance = new Holder();
// 这个 Holder 中相当于一个对象中只可以存储一份变量 相当于对当前对象的保护
Object instance = this.cachedAdaptiveInstance.get();
if (instance == null) {
//如果 Holder中的对象不存在,而且 存在error 则直接抛出异常
if (this.createAdaptiveInstanceError != null) {
throw new IllegalStateException("fail to create adaptive instance: " + this.createAdaptiveInstanceError.toString(), this.createAdaptiveInstanceError);
}
//加锁 防止并发时重复创建对象.
synchronized(this.cachedAdaptiveInstance) {
instance = this.cachedAdaptiveInstance.get();
if (instance == null) {
//双重校验,进一步防止代码在执行过程中,对象被创建
try {
//没有缓存的实例,则通过该方法创建.
instance = this.createAdaptiveExtension();
this.cachedAdaptiveInstance.set(instance);
} catch (Throwable var5) {
this.createAdaptiveInstanceError = var5;
throw new IllegalStateException("fail to create adaptive instance: " + var5.toString(), var5);
}
}
}
}
return instance;
}
getAdaptiveExtension() 方法是先通过缓存Holder获取对应的类型,返回参数为T 其实根据 this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); 确认得到的类型. 如果类型不存在,则需要调用createAdaptiveExtension 进行创建.
private T createAdaptiveExtension() {
try {
//先后去getAdaptiveExtensionClass 实例 然后在注入处理
return this.injectExtension(this.getAdaptiveExtensionClass().newInstance());
} catch (Exception var2) {
throw new IllegalStateException("Can not create adaptive extension " + this.type + ", cause: " + var2.getMessage(), var2);
}
}
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses(); // 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass(); // 没有找到@Adaptive类型实现,则动态创建一个AdaptiveExtensionClass
}
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get(); // 判断是否已经加载了当前Extension的所有实现类
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses(); // 如果还没有加载Extension的实现,则进行扫描加载,完成后赋值给cachedClasses变量
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
//获取SPI注解信息
SPI defaultAnnotation = (SPI)this.type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
// 获取SPI 中的Value
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
//value不为空而且有分割符号存在 则抛出异常
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + this.type.getName() + ": " + Arrays.toString(names));
}
// 选择SPI注入的value的name
if (names.length == 1) {
this.cachedDefaultName = names[0];
}
}
}
//然后在对应的 目录下寻找key为 SPI中注入的Value值的对象,并加载
Map<String, Class<?>> extensionClasses = new HashMap();
this.loadDirectory(extensionClasses, "META-INF/dubbo/internal/");
this.loadDirectory(extensionClasses, "META-INF/dubbo/");
this.loadDirectory(extensionClasses, "META-INF/services/");
return extensionClasses;
}
/**
* 加载目录下的 key value
*/
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
String fileName = dir + this.type.getName();
try {
ClassLoader classLoader = findClassLoader();
Enumeration urls;
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while(urls.hasMoreElements()) {
java.net.URL resourceURL = (java.net.URL)urls.nextElement();
this.loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable var7) {
logger.error("Exception when load extension class(interface: " + this.type + ", description file: " + fileName + ").", var7);
}
}
这里的步骤总结起来便是这样的
- 首先判断是否已经有缓存的实例对象,如果没有则需要创建AdaptiveExtensionClass实例
- 通过getExtensionClasses() 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来
- 判断是否已经加载了当前Extension的所有实现类,如果有则执行
- 如果还没有加载Extension的实现,则进行扫描( “META-INF/dubbo/internal/”,“META-INF/dubbo/”,“META-INF/services/”)加载,完成后赋值给cachedClasses变量
- 执行injectExtension 注入加载到的Key/value
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {// 处理所有set方法
Class<?> pt = method.getParameterTypes()[0];// 获取set方法参数类型
try {
// 获取setter对应的property名称
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
Object object = objectFactory.getExtension(pt, property); // 根据类型,名称信息从ExtensionFactory获取
if (object != null) { // 如果不为空,说set方法的参数是扩展点类型,那么进行注入
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
这里可以看到,扩展点自动注入的一句就是根据setter方法对应的参数类型和property名称从ExtensionFactory中查询,如果有返回扩展点实例,那么就进行注入操作。到这里getAdaptiveExtension方法就分析完毕了。
总结
- 每个ExtensionLoader 实例只负责加载一个特定扩展点实现
- 每个扩展点对应最多只有一个ExtensionLoader 实例
- 对于每个扩展点实现,最多只会有一个实例
- 一个扩展点实现可以对应多个名称(逗号分隔)
- 对于需要等到运行时才能决定使用哪一个具体实现的扩展点,应获取其自使用扩展点实现(AdaptiveExtension )
- @Adaptive 注解要么注释在扩展点==@SPI== 的方法上,要么注释在其实现类的类定义上
- 每个扩展点最多只能有一个被AdaptiveExtension
- 每个扩展点可以有多个可自动激活的扩展点实现(使用==@Activate==注解保证加载哪一个)
- 由于每个扩展点实现最多只有一个实例,因此扩展点实现应保证线程安全
- 如果扩展点有多个Wrapper,那么最终其执行的顺序不确定(内部使用ConcurrentHashSet存储)
参考文章:
https://blog.csdn.net/jdluojing/article/details/44947221