2.1 获取自适应拓展

getAdaptiveExtension 方法是获取自适应拓展的入口方法,因此下面我们从这个方法进行分析。相关代码如下:

  1. public T getAdaptiveExtension() {
  2. // 从缓存中获取自适应拓展
  3. Object instance = cachedAdaptiveInstance.get();
  4. if (instance == null) { // 缓存未命中
  5. if (createAdaptiveInstanceError == null) {
  6. synchronized (cachedAdaptiveInstance) {
  7. instance = cachedAdaptiveInstance.get();
  8. if (instance == null) {
  9. try {
  10. // 创建自适应拓展
  11. instance = createAdaptiveExtension();
  12. // 设置自适应拓展到缓存中
  13. cachedAdaptiveInstance.set(instance);
  14. } catch (Throwable t) {
  15. createAdaptiveInstanceError = t;
  16. throw new IllegalStateException("fail to create adaptive instance: ...");
  17. }
  18. }
  19. }
  20. } else {
  21. throw new IllegalStateException("fail to create adaptive instance: ...");
  22. }
  23. }
  24. return (T) instance;
  25. }

getAdaptiveExtension 方法首先会检查缓存,缓存未命中,则调用 createAdaptiveExtension 方法创建自适应拓展。下面,我们看一下 createAdaptiveExtension 方法的代码。

  1. private T createAdaptiveExtension() {
  2. try {
  3. // 获取自适应拓展类,并通过反射实例化
  4. return injectExtension((T) getAdaptiveExtensionClass().newInstance());
  5. } catch (Exception e) {
  6. throw new IllegalStateException("Can not create adaptive extension ...");
  7. }
  8. }

createAdaptiveExtension 方法的代码比较少,但却包含了三个逻辑,分别如下:

  1. 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
  2. 通过反射进行实例化
  3. 调用 injectExtension 方法向拓展实例中注入依赖

前两个逻辑比较好理解,第三个逻辑用于向自适应拓展对象中注入依赖。这个逻辑看似多余,但有存在的必要,这里简单说明一下。前面说过,Dubbo 中有两种类型的自适应拓展,一种是手工编码的,一种是自动生成的。手工编码的自适应拓展中可能存在着一些依赖,而自动生成的 Adaptive 拓展则不会依赖其他类。这里调用 injectExtension 方法的目的是为手工编码的自适应拓展注入依赖,这一点需要大家注意一下。关于 injectExtension 方法,前文已经分析过了,这里不再赘述。接下来,分析 getAdaptiveExtensionClass 方法的逻辑。

  1. private Class<?> getAdaptiveExtensionClass() {
  2. // 通过 SPI 获取所有的拓展类
  3. getExtensionClasses();
  4. // 检查缓存,若缓存不为空,则直接返回缓存
  5. if (cachedAdaptiveClass != null) {
  6. return cachedAdaptiveClass;
  7. }
  8. // 创建自适应拓展类
  9. return cachedAdaptiveClass = createAdaptiveExtensionClass();
  10. }

getAdaptiveExtensionClass 方法同样包含了三个逻辑,如下:

  1. 调用 getExtensionClasses 获取所有的拓展类
  2. 检查缓存,若缓存不为空,则返回缓存
  3. 若缓存为空,则调用 createAdaptiveExtensionClass 创建自适应拓展类

这三个逻辑看起来平淡无奇,似乎没有多讲的必要。但是这些平淡无奇的代码中隐藏了着一些细节,需要说明一下。首先从第一个逻辑说起,getExtensionClasses 这个方法用于获取某个接口的所有实现类。比如该方法可以获取 Protocol 接口的 DubboProtocol、HttpProtocol、InjvmProtocol 等实现类。在获取实现类的过程中,如果某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量。此时,上面步骤中的第二步条件成立(缓存不为空),直接返回 cachedAdaptiveClass 即可。如果所有的实现类均未被 Adaptive 注解修饰,那么执行第三步逻辑,创建自适应拓展类。相关代码如下:

  1. private Class<?> createAdaptiveExtensionClass() {
  2. // 构建自适应拓展代码
  3. String code = createAdaptiveExtensionClassCode();
  4. ClassLoader classLoader = findClassLoader();
  5. // 获取编译器实现类
  6. com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
  7. // 编译代码,生成 Class
  8. return compiler.compile(code, classLoader);
  9. }

createAdaptiveExtensionClass 方法用于生成自适应拓展类,该方法首先会生成自适应拓展类的源码,然后通过 Compiler 实例(Dubbo 默认使用 javassist 作为编译器)编译源码,得到代理类 Class 实例。接下来,我们把重点放在代理类代码生成的逻辑上,其他逻辑大家自行分析。