文章异常啰嗦且绕弯。java
JDK 版本 : Adoptopenjdk 14.0.1
IDE : idea 2020.2
Dubbo 版本 : dubbo 2.7.6spring
Dubbo Spi 是 Dubbo 框架扩展性的根本基础,是基于 jdk spi 的封装和扩展。apache
import org.apache.dubbo.common.extension.Adaptive; import org.apache.dubbo.common.extension.SPI; @SPI("dubbo") // spi 最主要的注解 public interface SpiDemoService { void sayHello(); }
一号实现类 :缓存
public class SpiDemoOneServiceImpl implements SpiDemoService { @Override public void sayHello() { System.out.println("hello 1"); } }
二号实现类 :app
public class SpiDemoTwoServiceImpl implements SpiDemoService { @Override public void sayHello() { System.out.println("hello 2"); } }
测试方法类:框架
import org.apache.dubbo.common.extension.ExtensionLoader; public class SpiTest { public static void main(String[] args) { // 获取 loader 工厂类 ExtensionLoader<SpiDemoService> loader = ExtensionLoader .getExtensionLoader(SpiDemoService.class); // 获取实体类 SpiDemoService one = loader.getExtension("one"); // 测试方法 one.sayHello(); } }
回到 demo :ide
ExtensionLoader<SpiDemoService> loader = ExtensionLoader .getExtensionLoader(SpiDemoService.class);
getExtensionLoader 是 ExtensionLoader 最核心的静态方法,用于获取 ExtensionLoader 实例学习
// org.apache.dubbo.common.extension.ExtensionLoader 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)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } // 先尝试获取,若是获取失败就建立一个 ExtensionLoader // EXTENSION_LOADERS 是一个静态 ConcurrentHashMap,用来存放 loader ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }
// org.apache.dubbo.common.extension.ExtensionLoader private ExtensionLoader(Class<?> type) { // 存储要建立的 loader 的类型 this.type = type; // objectFactory 是 ExtensionFactory 类型的对象,是用来依赖注入的工厂 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader .getExtensionLoader(ExtensionFactory.class) .getAdaptiveExtension()); }
// org.apache.dubbo.common.extension.ExtensionLoader public T getAdaptiveExtension() { // cachedAdaptiveInstance 是一个 Holder 对象,Holder 是对 Object 的包装 // 在此处先尝试获取实例化完成的对象,若是获取不到,就进入加载逻辑 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { // 若是以前初始化的时候报错了,那么错误会被记录下来并缓存在此处,直接抛出 // 此处的设计应该是减小锁消耗 if (createAdaptiveInstanceError != null) { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } synchronized (cachedAdaptiveInstance) { // 双锁验证 instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 建立实例并存储在 Holder 对象里 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { // 若是报错了就会把错误存储起来 createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } // 返回对象实例 return (T) instance; }
建立实例对象:测试
// org.apache.dubbo.common.extension.ExtensionLoader private T createAdaptiveExtension() { try { // getAdaptiveExtensionClass().newInstance() 方法会使用 Class 对象的 newInstance() 方法建立一个对象 // injectExtension(...) 则会对建立出来的对象进行依赖注入 return injectExtension((T)getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); } }
// org.apache.dubbo.common.extension.ExtensionLoader private T injectExtension(T instance) { // objectFactory 是用来依赖注入的 ExtensionFactory // 若是 objectFactory 为空,就直接返回 // 须要注意的是,只有非 ExtensionFactory 的 loader 才有 objectFactory if (objectFactory == null) { return instance; } try { // 轮训实例对象中全部的方法 for (Method method : instance.getClass().getMethods()) { // 若是方法不是 set 方法就跳过 // 此处能够理解为,dubbo 的 spi 依赖注入须要 set 方法支持 if (!isSetter(method)) { continue; } // 若是方法被标注了 DisableInject 注解就跳过 if (method.getAnnotation(DisableInject.class) != null) { continue; } // 若是方法的参数是原始类型就跳过 // 依赖注入须要使用包装类型 Class<?> pt = method.getParameterTypes()[0]; if (ReflectUtils.isPrimitives(pt)) { continue; } try { // 反射注入 String property = getSetterProperty(method); Object object = objectFactory.getExtension(pt, property); if (object != null) { method.invoke(instance, object); } } catch (Exception e) { logger.error("Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; }
ExtensionFactory 是用来依赖注入的工厂:this
@SPI public interface ExtensionFactory { <T> T getExtension(Class<T> type, String name); }
该接口在 Dubbo 中有三个默认实现类:
org.apache.dubbo.config.spring.extension.SpringExtensionFactory org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory org.apache.dubbo.common.extension.factory.SpiExtensionFactory
在开发中 SpringExtensionFactory 应该会用的更普遍一些,本示例中此处暂时不展开。
AdaptiveExtensionFactory 是默认工厂:
import org.apache.dubbo.common.extension.Adaptive; import org.apache.dubbo.common.extension.ExtensionFactory; import org.apache.dubbo.common.extension.ExtensionLoader; import java.util.ArrayList; import java.util.Collections; import java.util.List; @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; // 构造器 public AdaptiveExtensionFactory() { ExtensionLoader<ExtensionFactory> loader = ExtensionLoader .getExtensionLoader(ExtensionFactory.class); // AdaptiveExtensionFactory 会将 SpiExtensionFactory 和 SpringExtensionFactory 放置在 factories 列表里 List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); for (String name : loader.getSupportedExtensions()) { list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } // 使用 AdaptiveExtensionFactory 去获取实体类的时候, // 会调用 spi 或者 spring 的 ext 工厂去尝试获取实体类 @Override public <T> T getExtension(Class<T> type, String name) { for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; } }
import org.apache.dubbo.common.extension.ExtensionFactory; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; public class SpiExtensionFactory implements ExtensionFactory { @Override public <T> T getExtension(Class<T> type, String name) { // spi 工厂用于解析 spi 注解 if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { // 若是传入的 type 是一个被 spi 注释的接口,那么会初始化一个它的 class loader ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type); // 初始化对象 if (!loader.getSupportedExtensions().isEmpty()) { return loader.getAdaptiveExtension(); } } return null; } }
回到 demo :
SpiDemoService one = loader.getExtension("one");
// org.apache.dubbo.common.extension.ExtensionLoader public T getExtension(String name) { // 非空验证,忽略 if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } // 默认机制,会去找名称为 dubbo 的实例 // 通常用不到 if ("true".equals(name)) { return getDefaultExtension(); } // 若是以前不存在这个名称对应的 Holder 对象,此处会建立一个空白的 Holder // 调用 get() 方法会得到空对象 final Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { // 建立对象实例,并装进 holder 中 instance = createExtension(name); holder.set(instance); } } } // 返回实例 return (T) instance; }
// org.apache.dubbo.common.extension.ExtensionLoader private T createExtension(String name) { // 若是 class 不存在就报错 Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 尝试获取 class 对应的实例,若是不存在就建立 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 进行依赖注入 injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses; if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } initExtension(instance); return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }
spi 的代码有点绕,作一下总结。
ExtensionLoader 是整个 spi 系统的门面,也是 spi 的实例结合类。
内置对象
记录了 class 和 loader 的对应关系
记录了 class 和实例对象的对应关系。能够认为是一个静态的全局 bean 容器。
主要方法
尝试建立这个 class 对应的 loader 对象;
可是在建立通常 spi 接口的 loader 对象以前,还会先建立 ExtensionFactory 的 loader 对象。
按照需求实例化对象,放置到 EXTENSION_INSTANCES 对象中,而后作依赖注入并返回给使用者。
用来作依赖注入的工厂。
ExtensionFactory 也是被 ExtensionLoader 管理的一类特殊的 spi 类。
dubbo 的 spi 还有很重要的一部分即为 @Adaptive 注解的使用,这部分涉及动态代理,较为复杂,有空开新篇讲。
本文仅为我的的学习笔记,可能存在错误或者表述不清的地方,有缘补充