在Dubbo中, 無論是通過name
獲取指定擴展類, 還是自適應擴展,都會在加載完擴展,進行一次依賴注入,我們可以把這個稱爲Dubbo的IOC機制。
例如:
private T createExtension(String name) {
// throws any possible exception in loading period.
findException(name);
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw noExtensionException(name);
}
try {
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;
// 這裏會循環注入 Wrapper類最後返回的instance 是多個wrapper包裹之後的instance
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
// 注意這裏 IOC操作
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
T) wrapperClass.getConstructor(type).newInstance(instance)
是利用反射進行實例化。他的最外層injectExtension方法,所做的就是Dubbo的IOC,將擴展中的屬性進行賦值。接下來我們看一下他的實現
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
// 便利所有方法
for (Method method : instance.getClass().getMethods()) {
// 尋找set方法
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) {
// 執行setter方法,完成 IOC操作
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;
}
遍歷出類中所有的方法,尋找其中的set方法,根據方法命名獲取到需要從容器內搜索的對象的名稱,如果能搜索到,就利用反射進行注入。邏輯很清晰,唯一的疑惑點就是,根據名稱和類型搜索相應的對象的邏輯,也就是 Object object = objectFactory.getExtension(pt, property)
objectFactory
是怎麼來的呢?
private final ExtensionFactory objectFactory;
這是一個final變量,不可變,那我們去看他的構造方法去
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
很明顯這是在我們在開頭 通過接口的class 獲取 ExtentionLoader的時候,創建的
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
獲取到的是 AdaptiveExtensionFactory
的實例,因爲他的類上帶有 @Adaptive
註解.
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
@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;
}
}
所以最後就是它作爲擴展類,也就是objectFactory的實例對象。所以當調用objectFactory.getExtension
實際執行的是AdaptiveExtensionFactory的 getExtension
方法.
我們可以看到他是從factories
裏去拿, factories
是構造函數中初始化的.
list.add(loader.getExtension(name));
那麼我們在common子工程下,找到如下的SPI
擴展文件 META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
ExtensionFactory類型的擴展,出了ExtensionFactory有兩個,一個 SpiExtensionFactory
,另外一個是SpringExtensionFactory
SpiExtensionFactory
如何去搜索擴展呢? 我們去看代碼。
/**
* SpiExtensionFactory
*/
public class SpiExtensionFactory implements ExtensionFactory {
@Override
public <T> T getExtension(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension();
}
}
return null;
}
}
type是 接口,且帶有 @SPI註解的,獲取Adaptive
擴展。