dubbo自适应拓展机制 - litter-fish/ReadSource GitHub Wiki
原理
自适应拓展机制的实现逻辑:
- 首先 Dubbo 会为拓展接口生成具有代理功能的代码。
- 然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。
- 最后再通过反射创建代理类,整个过程比较复杂
Adaptive 注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})// Adaptive 可注解在类或方法上
public @interface Adaptive {
String[] value() default {};
}
- 当 Adaptive 注解在类上时,Dubbo 不会为该类生成代理类。 AdaptiveCompiler 和 AdaptiveExtensionFactory,此种情况, 表示拓展的加载逻辑由人工编码完成
- 注解在方法(接口方法)上时,Dubbo 则会为该方法生成代理逻辑,表示拓展的加载逻辑需由框架自动生成
获取自适应拓展
// com/alibaba/dubbo/common/extension/ExtensionLoader.java
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("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
创建自适应拓展
// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
* 1. 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
* 2. 通过反射进行实例化
* 3. 调用 injectExtension 方法向拓展实例中注入依赖,为手工编码的自适应拓展注入依赖
*/
private T createAdaptiveExtension() {
try {
// 获取自适应拓展类,并通过反射实例化
return
injectExtension( // 调用 injectExtension 方法向拓展实例中注入依赖, 为手工编码的自适应拓展注入依赖
(T) getAdaptiveExtensionClass() // 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
.newInstance()); // 通过反射进行实例化
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
获取自适应拓展 Class 对象
// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
* 首先,getExtensionClasses 这个方法用于获取某个接口的所有实现类。
* 比如该方法可以获取 Protocol 接口的 DubboProtocol、HttpProtocol、InjvmProtocol 等实现类。
* 在获取实现类的过程中,如果某个某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量。
* 此时,上面步骤中的第二步条件成立(缓存不为空),直接返回 cachedAdaptiveClass 即可。
* 如果所有的实现类均未被 Adaptive 注解修饰,那么执行第三步逻辑,创建自适应拓展类
* @return
*/
private Class<?> getAdaptiveExtensionClass() {
// 通过 SPI 获取所有的拓展类
getExtensionClasses();
// 检查缓存,若缓存不为空,则直接返回缓存
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 创建自适应拓展类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
创建自适应拓展类
// com/alibaba/dubbo/common/extension/ExtensionLoader.java
/**
* createAdaptiveExtensionClass 方法用于生成自适应拓展类,该方法首先会生成自适应拓展类的源码,
* 然后通过 Compiler 实例(Dubbo 默认使用 javassist 作为编译器)编译源码,得到代理类 Class 实例
* @return
*/
private Class<?> createAdaptiveExtensionClass() {
// 构建自适应拓展代码
String code = createAdaptiveExtensionClassCode();
ClassLoader classLoader = findClassLoader();
// 获取编译器实现类
com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译代码,生成 Class
return compiler.compile(code, classLoader);
}