通過spi擴展加載的時候,都是通過extensionloader來得到extension的,比如獲得一個exchanger:
public static Exchanger getExchanger(String type) {
return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
}
那么就是先拿到自己的extensionloader,然后利用這個loder去拿到extent-name對應的具體的擴展實例。
對於每一個extensionloader來說,除非自己是ExtensionFactory否則都有一個objectFactory,這個objectFactory本身通過擴展也是一個單例的adaptiveextension。
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
通過這個ExtensionLoader去拿到具體的extension的時候:
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
有兩種注入,一個是給自己的內部成員注入,另外就是自己被外層wrapper注入,反正都通過injectExtension來做的,具體看這個方法:
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
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);
}
}
}
}
}
就是對所有的set方法對應的屬性進行注入,通過objectFactory來完成的,這個factory是一個單例adaptive的,它的具體實現不是通過字節碼自動生成的,而是提前寫好的:
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;
}
對於adaptive來說,它里面含有有兩種facotry,spi和spring的,也就是只要有一個能夠通過他們兩個其中一個找到extension,那么就認為找到。
對於spi的facotry來說:
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;
}
找到對應的extensionloader(所有的loader都放在全局、靜態變量里面),然后直接返回適應性擴展。
也就是說dubbo幫你注入的不是一個具體extension,實際上也無法拿出來,因為只有在url給定具體的type以后才能給你真正對應的extension。
而在這里還沒有到url解析,所以只返回一個適應性擴展幫你注入。后面如果需要拿到具體的extension,需要結合url才可以做到。這也方便了每個實現者通過url進行自我定義,dubbo只是幫你注入了一個adaptive擴展,具體哪個擴展,你自己結合url去拿。
對於spring擴展來說:
public <T> T getExtension(Class<T> type, String name) {
for (ApplicationContext context : contexts) {
if (context.containsBean(name)) {
Object bean = context.getBean(name);
if (type.isInstance(bean)) {
return (T) bean;
}
}
}
return null;
}
這個就是依賴spring自己的context,比如定義了一個bean實現,想把它作為prover的imp-ref,那么就用這種方式。