共计 8473 个字符,预计需要花费 22 分钟才能阅读完成。
零 后期筹备
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.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;
}
2 ExtensionLoader 结构器
// 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());
}
二 getAdaptiveExtension
1 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;
}
2 createAdaptiveExtension
创立实例对象:
// 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);
}
}
3 injectExtension
// 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
ExtensionFactory 是用来依赖注入的工厂:
@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 应该会用的更宽泛一些,本示例中此处临时不开展。
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;
@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;
}
}
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.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;
}
2 createExtension
// 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);
}
}
五 一点唠叨
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 注解的应用,这部分波及动静代理,较为简单,有空开新篇讲。
本文仅为集体的学习笔记,可能存在谬误或者表述不清的中央,有缘补充