1. 程式人生 > >dubbo spi 講解分析

dubbo spi 講解分析

dex pla ssa mod 屬性 分代 循環 types 構造器註入

SPI

什麽是 SPI

Service Provider Interface , 服務提供接口。

JDK SPI

Java 的 spi 機制,是去掃描 /META-INF/service/ 的接口名文件,並獲取文件中的值。以 mysql 的驅動類來為案例。

用編輯器打開對應文件


ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class);
for(Command command:serviceLoader){
// 循環執行
command.execute();
}

這裏用到了 類的上下文加載器進下加載。

Java 通過 叠代器,循環加載對應文件中的類。

Dubbo SPI

途徑:ExtensionLoader.getExtension(String name) 實現路徑:

  • getExtensionLoader(Class<T> type) 就是為該接口 new 一個 ExtensionLoader,然後緩存起來。

  • getAdaptiveExtension() 獲取一個擴展類,如果 @Adaptive 註解在類上就是一個裝飾類;如果註解在方法上就是一個動態代理類,例如 Protocol$Adaptive 對象。

  • getExtension(String name) 獲取一個指定對象。

public static <T> ExtensionLoader
<T> getExtensionLoader(Class<T> type) {

// 刪除部分非空判斷代碼

// 先判斷擴展類是否已經存在
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null)
// 緩存 interface 對應的 dubbo spi 擴展加載類
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader
<T>(type));

loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}

private ExtensionLoader(Class<?> type) {
this.type = type;
// 創建工廠,即 dubbo 的 IOC 輸出中心,兩個實現類 [SpiExtensionFactory,SpringExtensionFactory]
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

public T getExtension(String name) {
// 刪除部分代碼
// 獲取一個實體類,其中持有一個 volatile 的 interface 實現類對象,保證內存可見性
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<Object>());
holder = cachedInstances.get(name);
}
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
// 創建一個 interface 的實例對象
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}

private T createExtension(String name) {
// 獲取對應的 name 的 class 加載類
Class<?> clazz = getExtensionClasses().get(name);
// 省略部分代碼
try {
// 緩存對應是否存在
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 註入對象
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
// 構造器註入,,,IOC
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
// 異常處理
}
}

private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
// 獲取方法名是 set 的屬性,進下屬性註入,,即 IOC
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
Class<?> pt = method.getParameterTypes()[0];
try {
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}

ExtensionLoader.getExtensionLoader(Class<T> type)

ExtensionLoader.getExtensionLoader(Container.class) -->this.type = type; -->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() -->this.type = type; -->objectFactory =null;

getExtension(String name) 核心調用鏈如下

getExtension(String name)

//指定對象緩存在cachedInstances;get出來的對象wrapper對象,例如protocol就ProtocolFilterWrapper和ProtocolListenerWrapper其中一個。

-->createExtension(String name) -->getExtensionClasses() -->injectExtension(T instance)//dubbo的IOC反轉控制,就是從spi和spring裏面提取對象賦值。 -->objectFactory.getExtension(pt, property) -->SpiExtensionFactory.getExtension(type, name) -->ExtensionLoader.getExtensionLoader(type) -->loader.getAdaptiveExtension() -->SpringExtensionFactory.getExtension(type, name) -->context.getBean(name) -->injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))//AOP的簡單設計

getAdaptiveExtension()

-->getAdaptiveExtension()//為cachedAdaptiveInstance賦值 -->createAdaptiveExtension() -->getAdaptiveExtensionClass() -->getExtensionClasses()//為cachedClasses 賦值 -->loadExtensionClasses() -->loadFile -->createAdaptiveExtensionClass()//自動生成和編譯一個動態的adpative類,這個類是一個代理類 -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension() -->compiler.compile(code, classLoader) -->injectExtension()//作用:進入IOC的反轉控制模式,實現了動態入註

總結

1、dubbo 設計了一系列緩存,jdk spi 不支持緩存;

2、dubbo 設計了默認初始化的類,jdk spi 不支持;

3、dubbo 動態獲取 SPI 對象,jdk spi 需進行 for 循環判斷;

4、dubbo 設計了 AOP 功能,XxxxFilterWrapper XxxxListenerWrapper;

5、dubbo 設計了 IOC 功能,wrapperClass.getConstructor(type).newInstance(instance);

dubbo spi 講解分析