通过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,那么就用这种方式。
原文地址:https://www.cnblogs.com/notlate/p/10229133.html