Dubbo 的依赖注入通过ExtensionFactory来获取依赖对象实例。
ExtensionFactory对象在ExtentionLoader的构造器中创建。
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null :
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
获取拓展点接口ExtensionFactory.class
的Adaptive实现类对象,这里得到的是AdaptiveExtensionFactory
实例,idea搜索其在dubbo-common包下的配置文件,文件名是org.apache.dubbo.common.extension.ExtensionFactory
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
AdaptiveExtensionFactory 内部维护了一个 ExtensionFactory 列表,用于存储其他类型的 ExtensionFactory。Dubbo 目前提供了两种 ExtensionFactory,分别是 SpiExtensionFactory 和 SpringExtensionFactory。前者用于注入对象是@SPI标注的接口类型;后者是用于从 Spring 的 IOC 容器中获取所需的拓展。
AdaptiveExtensionFactory
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
// 存储其他类型的 ExtensionFactory对象
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
//获取拓展点接口ExtensionFactory对应的ExtensionLoader
//每个拓展点接口都有一个对应的ExtensionLoader对象
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
//getSupportedExtensions得到所有非@Adaptive标注
//也非ExtensionFactory包装类的实现类的配置名
//getExtension通过配置名得到对象
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
// 返回一个不可更改的实例列表
factories = Collections.unmodifiableList(list);
}
//遍历所有其它ExtensionFactory实现类,调用它们的getExtension
@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;
}
}
AdaptiveExtensionFactory 内部维护了一个 ExtensionFactory 列表,用于存储其他类型的 ExtensionFactory。
getSupportedExtensions
得到所有非@Adaptive标注也非拓展点接口包装类的实现类的配置名集合。如:spi
spring
public Set<String> getSupportedExtensions() {
//获取cachedClasses中存储的map,该map的key为配置名
//value为实现类的class对象,指的是是那些即没有被@Adaptive标注也非包装类的类
Map<String, Class<?>> clazzes = getExtensionClasses();
//复制所有配置名,返回一个不可更改的set
return Collections.unmodifiableSet(new TreeSet<String>(clazzes.keySet()));
}
SpiExtensionFactory
用于创建自适应的拓展,有别于SpringExtensionFactory
public class SpiExtensionFactory implements ExtensionFactory {
// ExtensionFactory用来获取实现类对象,调用它的getExtension是传入的参数
// type代表setXxx方法参数的类型,也就是要注入的对象的类型
// name:指的是set出入的属性名,如setApple则name为apple
@Override
public <T> T getExtension(Class<T> type, String name) {
// 必须是拓展点接口
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
// 获取该拓展点接口对应的ExtensionLoader对象
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
// 如果该拓展点有其它的实现类,其它指的是既非@Adaptive标注也非该接口包装类
// 返回其Adaptive实现类
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension();
}
}
return null;
}
}
通过上面分析,在有其它实现类的情况下返回该拓展点接口的Adaptive自适应类,否则返回null。
自适应类:被@Adaptive标注或是动态生成的Adaptive实现类;
其它实现类:既非@Adaptive标注也非该接口包装类的实现类。
包装类:实现类有以该拓展点接口为唯一参数的构造器
SpringExtensionFactory
在Spring容器中通过name找到bean
public <T> T getExtension(Class<T> type, String name) {
//SPI should be get from SpiExtensionFactory
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
return null;
}
for (ApplicationContext context : contexts) {
if (context.containsBean(name)) {
Object bean = context.getBean(name);
if (type.isInstance(bean)) {
return (T) bean;
}
}
}
logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName());
if (Object.class == type) {
return null;
}
for (ApplicationContext context : contexts) {
try {
return context.getBean(type);
} catch (NoUniqueBeanDefinitionException multiBeanExe) {
logger.warn("Find more than 1 spring extensions (beans) of type " + type.getName() + ", will stop auto injection. Please make sure you have specified the concrete parameter type and there's only one extension of that type.");
} catch (NoSuchBeanDefinitionException noBeanExe) {
if (logger.isDebugEnabled()) {
logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe);
}
}
}
logger.warn("No spring extension (bean) named:" + name + ", type:" + type.getName() + " found, stop get bean.");
return null;
}
关于Spring与dubbo之后再分析