ExtensionLoader
通过前面文章的介绍我们已经知道通过ExtensionLoader可以获取到扩展接口实例对象,并且一个扩展接口对应着一个ExtensionLoader实例对象。ExtensionLoader是Dubbo SPI的实现核心,所以我们需要深入到源码研究它。
ExtensionLoader的缓存数据
ExtensionLoader存放在dubbo-common模块,它加载扩展接口快速的原因就是因为它使用了很多的缓存数据,并且以成员变量形式包含在类结构中,可以将这些缓存数据分为两大类:全局缓存(静态变量)和私有缓存(私有变量)。
全局缓存
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
SERVICES_DIRECTORY、DUBBO_DIRECTORY和DUBBO_INTERNAL_DIRECTORY这三个属性表示的是Dubbo在初始化加载扩展实现类的时候扫描的扩展配置文件位置,在Dubbo框架中实际上只使用到了DUBBO_INTERNAL_DIRECTORY这个目录位置META-INF/dubbo/internal。
EXTENSION_LOADERS是一个Map类型的静态变量,用来缓存所有扩展接口和对应的ExtensionLoader实例对象。
EXTENSION_INSTANCES也是一个Map类型的静态变量,用来缓存所有普通扩展实现类和对应的实例对象。
私有缓存
private final Class<?> type;
private final ExtensionFactory objectFactory;
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
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;
private volatile Throwable createAdaptiveInstanceError;
private Set<Class<?>> cachedWrapperClasses;
private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
type表示当前ExtensionLoader实例对象对应的扩展接口类型。
objectFactory主要用来实现Dubbo SPI的IOC特性。
cachedNames用于缓存普通扩展实现类和name的对应关系,和扩展配置文件中的配置key=value对应。
cachedClasses的内容和cachedNames相同,将cachedNames键值对调换即可得到cachedClasses。
cachedInstances存储扩展名称和扩展类对象的对应关系。如何该扩展接口包含有包装扩展类,那么扩展类对象将存储包装扩展类对象。
cachedAdaptiveInstance和cachedAdaptiveClass分别存储扩展接口的自适应扩展类对象和Class。
cachedDefaultName存储该扩展接口的默认扩展实现类,对应注解@SPI的value值。
ExtensionLoader加载过程
通过执行ExtensionLoader.getExtensionLoader(XXX.class)可以获取到扩展接口对应的ExtensionLoader实例对象,下面图是ExtensionLoader加载流程图:
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
......//省略代码
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;
}
断点执行上篇文章的例子,进入到getExtensionLoader()方法,type为PrintService.class,首先是通过EXTENSION_LOADERS获取扩展接口对应的ExtensionLoader对象,如果为空则new一个ExtensionLoader对象,并且缓存起来之后赋值给loader再返回。
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
实例化ExtensionLoader过程只处理type和objectFactory,type表示当前扩展接口类型,objectFactory是一个ExtensionFactory类型变量,当type不是ExtensionFactory.class时通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()赋值给objectFactory,ExtensionFactory同样是一个扩展接口:
@SPI
public interface ExtensionFactory {
<T> T getExtension(Class<T> type, String name);
}
那么又会进入了getExtensionLoader()方法,此时type为ExtensionFactory.class,EXTENSION_LOADERS也不存在缓存实例,同样需要创建ExtensionLoader实例,只不过此时的type变成了ExtensionFactory.class,所以objectFactory直接赋值null。
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;
执行完new ExtensionLoader(ExtensionFactory.class)之后,存放缓存里面返回。这样就可以获取到了ExtensionFactory对应的ExtensionLoader对象,获取到ExtensionLoader之后执行getAdaptiveExtension()方法即:
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()获取到ExtensionFactory的自适应扩展类AdaptiveExtensionFactory实例。
objectFactory赋值之后,PrintService.class类型的ExtensionLoader就创建完成了,紧接着赋值给缓存EXTENSION_LOADERS,最后将实例loader返回,这样整个ExtensionLoader的加载过程就完成了。
后面文章会陆续对ExtensionFactory类和getAdaptiveExtension()方法进行详细解析。