目录
2.1 private final Holder>> cachedClasses = new Holder<>();
2.3 cachedAdaptiveInstance 缓存扩展类的instance
3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程
3.1、ExtensionLoader loader 中只有一个type属性对应
获取到ObjectFactory后返回对应的ExtensionLoader
四 第二步 首先通过getAdaptiveExtension回去自适应对象
1、前文
在前面四章进行了了解dubbo中的默认服务发现、调用等逻辑后,本章对Dubbo中使用的SPI技术进行了解。
SPI全称为Service Provider Interface,Java SPI可以自行了解,本文不做叙述。
2、Dubbo SP
案例一:ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
首先查看getExtensionLoader方法做了什么:
第一步 首先获取对应的ExtensionLoader对象
@SuppressWarnings("unchecked")
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 an interface!");
}
if (!withExtensionAnnotation(type)) {// 判断接口是否使用了@SPI注解
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
// 初次加载为null 需要进行new
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); //根据type生成指定的ExtensionLoader
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
首先是对其进行一些列的参数校验等,然后通过
private ExtensionLoader(Class<?> type) {
this.type = type;
// 首先生成指定的ExtensionFactory的自适应扩展类 Adaptive根据参数动态配置
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
此处type为ExtensionFactory的时候直接用null否则通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() 生成对应的
ExtensionFactory
二 代码中缓存对象
@Adaptive @Spi等注解来表示对应是自适应扩展类,或是spi等
实际就是根据不同文件路径的对象进行缓存响应的class信息等
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 Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com