零 后期筹备
0 FBI WARNING
文章异样啰嗦且绕弯。
1 版本
JDK 版本 : Adoptopenjdk 14.0.1
IDE : idea 2020.2
Dubbo 版本 : dubbo 2.7.6
2 Spi 简介
Dubbo Spi 是 Dubbo 框架扩展性的基本根底,是基于 jdk spi 的封装和扩大。
3 Demo
3.1 须要扩大的接口类
import org.apache.dubbo.common.extension.Adaptive;import org.apache.dubbo.common.extension.SPI;@SPI("dubbo") // spi 最次要的注解public interface SpiDemoService { void sayHello(); }
3.2 接口实现类
一号实现类 :
public class SpiDemoOneServiceImpl implements SpiDemoService { @Override public void sayHello() { System.out.println("hello 1"); }}
二号实现类 :
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(); }}
一 getExtensionLoader
回到 demo :
ExtensionLoader<SpiDemoService> loader = ExtensionLoader .getExtensionLoader(SpiDemoService.class);
1 getExtensionLoader
getExtensionLoader 是 ExtensionLoader 最外围的静态方法,用于获取 ExtensionLoader 实例
// org.apache.dubbo.common.extension.ExtensionLoaderpublic 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; }
2 ExtensionLoader 结构器
// org.apache.dubbo.common.extension.ExtensionLoaderprivate ExtensionLoader(Class<?> type) { // 存储要创立的 loader 的类型 this.type = type; // objectFactory 是 ExtensionFactory 类型的对象,是用来依赖注入的工厂 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader .getExtensionLoader(ExtensionFactory.class) .getAdaptiveExtension()); }
二 getAdaptiveExtension
1 getAdaptiveExtension
// org.apache.dubbo.common.extension.ExtensionLoaderpublic 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;}
2 createAdaptiveExtension
创立实例对象:
// org.apache.dubbo.common.extension.ExtensionLoaderprivate 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); }}
3 injectExtension
// org.apache.dubbo.common.extension.ExtensionLoaderprivate 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
ExtensionFactory 是用来依赖注入的工厂:
@SPIpublic interface ExtensionFactory { <T> T getExtension(Class<T> type, String name);}
该接口在 Dubbo 中有三个默认实现类:
org.apache.dubbo.config.spring.extension.SpringExtensionFactoryorg.apache.dubbo.common.extension.factory.AdaptiveExtensionFactoryorg.apache.dubbo.common.extension.factory.SpiExtensionFactory
在开发中 SpringExtensionFactory 应该会用的更宽泛一些,本示例中此处临时不开展。
1 AdaptiveExtensionFactory
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;@Adaptivepublic 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; }}
2 SpiExtensionFactory
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; }}
四 getExtension
回到 demo :
SpiDemoService one = loader.getExtension("one");
1 getExtension
// org.apache.dubbo.common.extension.ExtensionLoaderpublic 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;}
2 createExtension
// org.apache.dubbo.common.extension.ExtensionLoaderprivate 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); }}
五 一点唠叨
1 总结
spi 的代码有点绕,做一下总结。
ExtensionLoader
ExtensionLoader 是整个 spi 零碎的门面,也是 spi 的实例联合类。
内置对象
- EXTENSION_LOADERS
记录了 class 和 loader 的对应关系
- EXTENSION_INSTANCES
记录了 class 和实例对象的对应关系。能够认为是一个动态的全局 bean 容器。
次要办法
- getExtensionLoader(Class)
尝试创立这个 class 对应的 loader 对象;
然而在创立个别 spi 接口的 loader 对象之前,还会先创立 ExtensionFactory 的 loader 对象。
- getExtension(String)
依照需要实例化对象,搁置到 EXTENSION_INSTANCES 对象中,而后做依赖注入并返回给使用者。
ExtensionFactory
用来做依赖注入的工厂。
ExtensionFactory 也是被 ExtensionLoader 治理的一类非凡的 spi 类。
2 未实现
dubbo 的 spi 还有很重要的一部分即为 @Adaptive 注解的应用,这部分波及动静代理,较为简单,有空开新篇讲。
本文仅为集体的学习笔记,可能存在谬误或者表述不清的中央,有缘补充