dubbo的SPI加载机制分析
如何加载对应类
在dubbo中通过ExtensionLoader来实现对应的类,来看看具体的代码实现。
首先来看看它的加载类ExtensionLoader类的实现:
1 | public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { |
由于EXTENSION_LOADERS.get(type)为空;,那么接下来会执行EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader
其代码表现形式为:1
2
3
4private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
当调用的Type不为ExtensionFactory.class时,会调用getAdaptiveExtension这个方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
这段代码重点关注createAdaptiveExtension()这个方法:
1 | private T createAdaptiveExtension() { |
其中核心的步骤在于getAdaptiveExtensionClass这个方法,下面有个getExtensionClasses方法,顾名思义,就是拿到所有的扩展类。
1 | private Map<String, Class<?>> getExtensionClasses() { |
这里有一个loadExtensionClasse方法:它主要是加载
1 | private Map<String, Class<?>> loadExtensionClasses() { |
其中比较核心的是loadFile这个方法,该方法从指定文件夹中读取对应的文件并将类实例化或者缓存到HashMap中。分别从三个文件夹下获取:
- META-INF/services/
- META-INF/dubbo/
- META-INF/dubbo/internal
其文件夹下面保存文件的形式分别是这种:
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
而且有意思的是这个类必须继承自文件的名字,因为文件的名字即为类的名字。把相关的类加载或者扩展加载进来。带有Adaptive注解的是默认的即将加载的类。没有带的将缓存到cachedClasses中。接着就是调用构造函数生成一个新的实例。
获取类的实例
如果有多个实例,想要通过name获取对应的实例,可以通过
ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension(“impl1”)
这个方法获取。
总结
大概分析完了dubbo的类加载机制,其实它本质就是通过配置加上注解来实现的。我们也可以自己动手写一个简单的类加载实例。