1-2.获取自适应扩展
通过1-0.SPI可以知道,ExtensionLoader创建的具体实现都是自适应扩展。ExtensionLoader通过getAdaptiveExtension()方法获取自适应扩展:
public 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("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
对于每一个接口来说,只需要生成一个自适应代理,自适应代理会将方法代理到具体的实现类。因此自适应代理只需要缓存一个,即cachedAdaptiveInstance。真正的创建自适应代理是在createAdaptiveExtension()方法中。
private T createAdaptiveExtension() {
try {
// 依赖注入
return injectExtension((T)
// 获取自适应扩展类的Class对象
getAdaptiveExtensionClass()
// 通过反射创建实例
.newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
对于injectExtension(...)在之前的1-1.获取扩展类实现已经介绍过了,这里主要介绍如何获取自适应扩展类的Class对象。
现在已知的获取自适应扩展类的Class对象的方法有两种:
- 通过给自定义的扩展类添加
@Adaptive注解,关于这点可以参考1-1.获取扩展类实现 - 通过Dubbo自动生成自适应扩展类,即
createAdaptiveExtensionClass()方法;
private Class<?> getAdaptiveExtensionClass() {
// 获取所有扩展类实例
getExtensionClasses();
// 如果cachedAdaptiveClass不为空
// 则证明出现了第一种情况
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 通过Dubbo创建自适应扩展类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
对于JVM来说Class类文件的形式可以有很多种,可以参考JVM虚拟机类加载机制笔记,因此,我们可以使用JVM的机制动态加载Class文件。createAdaptiveExtensionClass()就是通过该方式处理的,不过区别是Dubbo不是直接生成Class文件,而是生成源代码,然后编译、加载:
private Class<?> createAdaptiveExtensionClass() {
// 生成Java代码
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
// 获取类加载器
ClassLoader classLoader = findClassLoader();
// 获取编译器
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译代码,获取Class文件
return compiler.compile(code, classLoader);
}
这个方法中,我们主要关心的有两部分:
- AdaptiveClassCodeGenerator如何生成代码的
- Compiler如何编译源代码生成Class对象的
我们对这两部分分别进行讨论。
1.1 AdaptiveClassCodeGenerator
AdaptiveClassCodeGenerator是自适应扩展类的代码生成器。