} catch (Throwable t) {
// 异常信息缓存起来,下一次进来时如果发现是创建实例是出现异常,就直接抛出异常。这里的设计应该是当扩展点创建异常时避免多次执行创建流程的优化
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
该方法主要做了以下几件事
-
从缓存cachedAdaptiveInstance中获取扩展点实现,存在该扩展点对象,则直接返回该实例。cachedAdaptiveInstance是一个Holder对象,主要用于缓存该扩展点的实现的具体实例,因为这里只会返回一个自适应扩展点的实现(有多个实现类标注了则按文件定义顺序取最后一个),实现对于每个``ExtensionLoader`来说,自适应扩展点是单例的。
-
如果扩展点实现不存在,调用createAdaptiveExtension()创建一个具体的实现,并将该实例set到cachedAdaptiveInstance中缓存起来。
创建扩展点实现的具体流程是在createAdaptiveExtension方法中
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
该方法主要做了以下几件事
-
调用getExtensionClasses(),顾名思义,该方法主要是获取扩展点的所有实现的.class对象。
-
如果缓存的cachedAdaptiveClass 对象不为null,直接返回。(cachedAdaptiveClass是一个class对象,用于保存该扩展点的自适应扩展点的实现,即是该扩展点的实现类中存在有将@Adaptive标注在类上的默认自适应扩展点)
-
如果为缓存有cachedAdaptiveClass对象,则调用createAdaptiveExtensionClass创建一个cachedAdaptiveClass,并复制给cachedAdaptiveClass
接下来首先进入getExtensionClasses()方法
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
该方法首先会从cachedClasses(cachedClasses也是一个holder,用于存储每个扩展点的所有扩展实现的map集合)获取该.class对象,存在则直接返回,否则调用loadExtensionClasses方法加载扩展点的classs,将加载到的classes存到cachedClasses中。
接下来进入loadExtensionClasses
private Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
for (LoadingStrategy strategy : strategies) {
// 扫描每个加载策略目录中的扩展点实现
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
// 对alibaba的践行兼容
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace(“org.apache”, “com.alibaba”), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
}
return extensionClasses;
}
首先调用cacheDefaultExtensionName()方法。再给接口标注@SPI的时候,可以给个默认的value值,表示指定的默认的扩展点实现,如@S