dubbo的dubbo-common工程中大量使用了动态扩展。
序列化由基类/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/Serialization.java可以扩展成:dubbo,fst,hessian,java,json,kryo
日志由基类/dubbo-common/src/main/java/com/alibaba/dubbo/common/logger/Logger.java可以扩展成:jcl,jdk,log4j,slf4j
实例化对象的方式
ExtensionLoader<HasAdaptiveExt> loader = ExtensionLoader.getExtensionLoader(HasAdaptiveExt.class);
HasAdaptiveExt ext = loader.getAdaptiveExtension();
1)如果extensionLoader没有初始化会先初始化extensionLoader
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
实例化过程:
调用堆栈:
ExtensionLoader<T>.loadFile(Map<String,Class<?>>, String) line: 598ExtensionLoader<T>.loadExtensionClasses() line: 591
ExtensionLoader<T>.getExtensionClasses() line: 567
ExtensionLoader<T>.getAdaptiveExtensionClass() line: 728
ExtensionLoader<T>.createAdaptiveExtension() line: 721
ExtensionLoader<T>.getAdaptiveExtension() line: 455
ExtensionLoader_Adaptive_Test.test_useAdaptiveClass() line: 48
2)扫描三个路径下的配置文件
loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadFile(extensionClasses, DUBBO_DIRECTORY);
loadFile(extensionClasses, SERVICES_DIRECTORY);
META-INF/dubbo/internal/
META-INF/dubbo/
META-INF/services/
配置文件采用基类包名.类名的命名方式,如/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt
3)生成实例化对象
1. 读取基类@SPI注解中设定的默认示例化对象
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
2. loadFile中读配置文件,生成class
<span style="color:#ff0000;">Class<?> clazz = Class.forName(line, true, classLoader);</span>
if (! type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + "is not subtype of interface.");
}
if (clazz.isAnnotationPresent(Adaptive.class)) {
if(cachedAdaptiveClass == null) {
<span style="color:#ff0000;"> cachedAdaptiveClass = clazz;</span>
} else if (! cachedAdaptiveClass.equals(clazz)) {
throw new IllegalStateException("More than 1 adaptive class found: "
+ cachedAdaptiveClass.getClass().getName()
+ ", " + clazz.getClass().getName());
}
}
3.生成实例化对象
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
}
}