通过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,那么就用这种方式。