Dubbo源码解析-ExtensionFactory

本文介绍Dubbo中依赖注入的实现方式,主要通过ExtensionFactory获取依赖对象实例。详细解析了AdaptiveExtensionFactory、SpiExtensionFactory及SpringExtensionFactory的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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之后再分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值