1. ExtensionLoader类介绍
咱们dubbo spi扩展技术主要是在ExtensionLoader 中实现的,包括寻找扩展,创建扩展,缓存扩展等扩展管理的整个生命周期,同时也对外提供类获取扩展的功能。其实一个ExtensionLoader对象就代表着一个需要扩展的接口,然后里面缓存了它的扩展点实现类。
1.1寻找扩展的方法:
1.2创建扩展的方法:
1.3缓存扩展(提供了一系列对象元素进行缓存):
1.4 外提供类获取扩展:
当然不局限于这些方法,这里只是大体说一下,后面详细分析。
2.ExtensionLoader类成员介绍
// java spi技术配置位置
private static final String SERVICES_DIRECTORY = "META-INF/services/";
// dubbo spi 技术配置文件位置
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
// dubbo spi 框架本身配置文件位置
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
// 缓存 extensionloader 们
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
// 缓存了instance , key是 class对象,value 是对应的实例 , 扩展实现类集合
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
这几个类成员主要是定义扩展配置文件的位置与缓存ExtensionLoader对象。
3.ExtensionLoader成员变量介绍
private final Class<?> type;//接口类型 , 扩展接口
private final ExtensionFactory objectFactory;// factory 一般是适配类 AdaptiveExtensionFactory
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>(); // 存储 class s
private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
private volatile Class<?> cachedAdaptiveClass = null;
private String cachedDefaultName; // 默认的 @SPI("dubbo")
private volatile Throwable createAdaptiveInstanceError;
private Set<Class<?>> cachedWrapperClasses;
private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
这些成员变量,主要是缓存当前ExtensionLoader对象的扩展接口类型,缓存扩展点实现类,自适应类,包装类等等。
4.窥探ExtensionLoader对象创建
ExtensionLoader类的构造方法是private的,我们不能通过外部new的方式来创建对象。ExtensionLoader提供了static方法来供我们获取自己想要的ExtensionLoader对象。
咱们先从 getExtensionLoader(Class type) 方法开始,
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 interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
}
// 先从缓存中查找
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {// dubbo 中很多的处理都是这样的 创建先put 然后再get 获取值,保证线程安全
//创建
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
在getExtensionLoader方法中,首先判断你传过来的type (也就是扩展点接口类型)不能是null,而且类型还需要是个interface,之后就是判断有没有@SPI注解,再往下走就是从EXTENSION_LOADERS这个map中获取该类型的ExtensionLoader对象,如果没有获取到的话就new ExtensionLoader(type),然后使用putIfAbsent方法put,不存在就put到map中,之后再获取一遍返回。
接着我们再看看new ExtensionLoader(type) 这个构造
private ExtensionLoader(Class<?> type) {
this.type = type;
//扩展工厂
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
首先是将type 赋值给成员变量type,相当于缓存起来,接着判断type是不是ExtensionFactory类型的,如果不是的话就通过ExtensionFactory 的ExtensionLoader对象获取它的自适应扩展对象,在这里也就是AdaptiveExtensionFactory 对象,然后将这个对象赋值给objectFactory成员。如果是ExtensionFactory类型的,objectFactory赋值null;
该部分就是ExtensionLoader对象创建源码了,接下来我们在看下扩展实现类的具体创建过程。
5.扩展点实现类对象创建过程
在dubbo中,getExtensionLoader(Class type) 方法往往与 getExtension(String name) 方法组合使用,也就是获取到某个扩展点ExtensionLoader对象后接着通过name获取具体的实现类。
public T getExtension(String name) {
//判空
if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
// 从缓存中根据name获取实现类对象
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<Object>());
holder = cachedInstances.get(name);
}
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
首先是参数校验,然后就是从实现类缓存的成员中获取该name的实现类holder,如果没有找到就创建一个。
接着就是调用holder.get()方法,获取到具体的实现类。这里我们要先看下这个holder是什么。
public class Holder<T> {
private volatile T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
可以看出holder中封装了一个修饰的volatile成员。
接着上面的话题,如果没有在Holder获取到具体的value,也就是value是null。这时走了createExtension(name) 方法。然后将createExtension(name) 方法返回值设置到holder中。
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);// setter 注入
Set<Class<?>> wrapperClasses = cachedWrapperClasses; //所有的wrapper缓存
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {// 包装Wrapper
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
createExtension方法第一行就调用getExtensionClasses()方法,其实这个方法作用就是从配置文件中获取实现类的class们,它的返回值是Map<String, Class<?>> ,key就是咱们的name,然后value就对应的是扩展实现类的class,getExtensionClasses()这个方法稍后再说,这个就当作***问题一*** , 这里咱们就当Class<?> clazz = getExtensionClasses().get(name);这行有了返回值,接着往下走,从EXTENSION_INSTANCES 这个成员变量中获取这个class对应的具体实例,如果没有,就执行clazz.newInstance()创建一个然后塞到EXTENSION_INSTANCES 这个成员中缓存。接着往下
走injectExtension(instance);这个就是具体的setter注入,这个咱们后面说,就当作咱们的***问题二***,再往后就是这个扩展点有包装类的话,就将扩展点对象传入到包装类的构造中进行包装,这个就当作咱们***问题三***,到这里咱们想要的具体对象就创建完成了。
6.本篇总结
本篇主要说了ExtensionLoader 类在dubbo spi的地位作用,它管理了扩展点实现的生命周期,实现了自适应,IOC,自动包装等特性,之后我们又介绍了ExtensionLoader 的类成员与成员变量,这些成员主要是用作扩展点实现类的缓存,之后我们又说了ExtensionLoader 的创建过程与扩展点实现类的创建过程,其中我们还遗留了3个问题,
1.扩展点实现类具体寻找过程
2.setter注入过程
3.包装类的规则与包装原理
这个三个问题会在后面篇章讲述。