Skip to content

服务器托管,北京服务器托管,服务器租用-价格及机房咨询

Menu
  • 首页
  • 关于我们
  • 新闻资讯
  • 数据中心
  • 服务器托管
  • 服务器租用
  • 机房租用
  • 支持中心
  • 解决方案
  • 联系我们
Menu

dubbo源码之-ExtensionInjector

Posted on 2023年9月20日2023年9月20日 by hackdl

dubbo源码之-ExtensionInjector

  • 概述
  • 源码入口
  • Extension 是如何获取到?
  • SpiExtensionInjector

概述

其实ExtensionInjector 非常简单, 我们知道dubbo有ioc注入的功能, 是靠的set方法注入,对应的底层源码主要是ExtensionInjector

如果不知道dubbo的ioc 参考 dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别

源码入口

总结:
1.set方法注入条件:set开头,参数只有一个,public修饰
2.set方法上没有使用 DisableInject 注解
3.set 方法是在ScopeModelAware 系列中声明的也不能注入

org.apache.dubbo.common.extension.ExtensionLoader#injectExtension

private T injectExtension(T instance) {
        if (injector == null) {
            return instance;
        }

        try {
            //获取当前对象的当前类的所有方法
            for (Method method : instance.getClass().getMethods()) {
                //是否为set方法 不是的话则跳过,在这里合法的set方法满足3个条件:
                //set开头,参数只有一个,public修饰
                if (!isSetter(method)) {
                    continue;
                }
                /**
                 * Check {@link DisableInject} to see if we need auto-injection for this property
                 */
                //方法上面是否有注解DisableInject修饰,这种情况也直接跳过
                if (method.isAnnotationPresent(DisableInject.class)) {
                    continue;
                }

                // When spiXXX implements ScopeModelAware, ExtensionAccessorAware,
                // the setXXX of ScopeModelAware and ExtensionAccessorAware does not need to be injected
                if (method.getDeclaringClass() == ScopeModelAware.class) {
                    continue;
                }
                if (instance instanceof ScopeModelAware || instance instanceof ExtensionAccessorAware) {
                    if (ignoredInjectMethodsDesc.contains(ReflectUtils.getDesc(method))) {
                        continue;
                    }
                }

                Class> pt = method.getParameterTypes()[0];
                //方法的参数如果是原生类型也跳过
                if (ReflectUtils.isPrimitives(pt)) {
                    continue;
                }

                try {
                    //获取set方法对应的成员变量如setProtocol 属性为protocol
                    String property = getSetterProperty(method);
                    //根据参数类型如Protocol和属性名字如protocol获取应该注入的对象
                    Object object = injector.getInstance(pt, property);
                    if (object != null) {
                        //执行对应对象和对应参数的这个方法
                        method.invoke(instance, object);
                    }
                } catch (Exception e) {
                    logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "",
                        "Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(),
                        e);
                }
            }
        } catch (Exception e) {
            logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "", e.getMessage(), e);
        }
        return instance;
    }

Extension 是如何获取到?

这一行的关键是需要知道injector的实例

Object object = injector.getInstance(pt, property);

在ExtensionLoader中 是一个属性, 在构造方法中进行的初始化
private final ExtensionInjector injector;

//如果当前扩展类型为扩展注入器类型则设置当前注入器变量为空,否则的话获取一个扩展注入器扩展对象
        //1)这里有个type为空的判断,普通的扩展类型肯定不是ExtensionInjector类型 这里必定会为每个非扩展注入ExtensionInjector类型创建一个ExtensionInjector类型的扩展对象,
//2) 这里代码会走extensionDirector.getExtensionLoader(ExtensionInjector.class),这个代码会创建一个为ExtensionInjector扩展对象的加载器对象ExtensionLoader
//3) getAdaptiveExtension() 这个方法就是通过扩展加载器获取具体的扩展对象的方法我们会详细说
this.injector = (type == ExtensionInjector.class ?null : extensionDirector.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension());

根据上面的代码可以知道 injector 是 ExtensionInjector 一个实现类型有Adaptive注解的实现类,从上uml类图上可以知道是:AdaptiveExtensionInjector

initialize 方法在ExtensionLoader的初始化的时候调用,也就是说获取到ExtensionInjector的所有非自适应的实现类

@Override
    public void initialize() throws IllegalStateException {
        ExtensionLoader loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
        injectors = loader.getSupportedExtensions().stream()
            .map(loader::getExtension)
            .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
        //collectingAndThen 去重操作
    }

从中我们可以看到从
//ScopeBeanExtensionInjector
//SpiExtensionInjector
//SpringExtensionInjector
三者中获取实例,只获取第一个非空实例

//可以看到上面代码按扩展注入器顺序来遍历的第一个找到的对象就直接返回了,
    //这个AdaptiveExtensionInjector在初始化的时候会获取所有的ExtensionInjector的扩展,非自适应的,它本身自适应的扩展,
    // 这里会获取非自适应的扩展列表一共有3个按顺序为:
    //ScopeBeanExtensionInjector
    //SpiExtensionInjector
    //SpringExtensionInjector
    @Override
    public  T getInstance(final Class type, final String name) {
        //遍历所有的扩展注入器,如果可以获取到扩展对象则直接返回
        return injectors.stream()
            .map(injector -> injector.getInstance(type, name))
            .filter(Objects::nonNull)
            .findFirst()
            .orElse(null);
    }

SpiExtensionInjector

其他的不做过多解释 ,今天只写一下这个SpiExtensionInjector吧

@Override
    public  T getInstance(final Class type, final String name) {
        //如果是一个标准的被@SPI注解修饰的扩展接口则满足条件
        if (!type.isInterface() || !type.isAnnotationPresent(SPI.class)) {
            return null;
        }
        //使用扩展访问器来获取对应类型的扩展加载器
        ExtensionLoader loader = extensionAccessor.getExtensionLoader(type);
        if (loader == null) {
            return null;
        }
        //使用对应类型的扩展加载器来加载自适应扩展 这个加载的扩展可以参考4.4.6小节
        if (!loader.getSupportedExtensions().isEmpty()) {
            return loader.getAdaptiveExtension();
        }
        return null;
    }

服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net

相关推荐: Python中的具名元组类用法

>>> from collections import namedtuple >>> Point = namedtuple(‘Point’, [‘x’, ‘y’, ‘z’]) #创建具名元组类 >>> Po…

Related posts:

  1. 租用台湾服务器哪个机房好
  2. 四川电信服务器托管价格调查
  3. Linux系统调优介绍
  4. OpenAI 发布GPT-4——全网抢先体验 OpenAI 发布GPT-4
  5. wsl 中 docker-compose 搭建 kafka 集群出现的外部访问错误

服务器托管,北京服务器托管,服务器租用,机房机柜带宽租用

服务器托管

咨询:董先生

电话13051898268 QQ/微信93663045!

上一篇: R语言逐步多元回归模型分析长鼻鱼密度影响因素|附代码数据
下一篇: 逍遥自在学C语言 | 指针函数与函数指针

最新更新

  • 持续测试新范式:拨压测一体化
  • Eyeshot 2023.2 Crack by Xacker Eyeshot FemEyeshot 2023.2
  • Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档
  • Spring Boot 2.1.0正式发布
  • 一文带你从了解到搭建 HTTP/3 Web 服务

随机推荐

  • 北京服务器租用,北京租赁中心2022年更新
  • 西安最佳服务器托管服务推荐
  • 最新服务器托管报价图片欣赏
  • One-Shot Verifiable Encry
  • 蒙鸟云高防服务器托管租用

客服咨询

  • 董先生
  • 微信/QQ:93663045
  • 电话:13051898268
  • 邮箱:dongli@hhisp.com
  • 地址:北京市石景山区重聚园甲18号2层

友情链接

  • 服务器托管
  • 机房租用托管
  • 服务器租用托管
©2023 服务器托管,北京服务器托管,服务器租用-价格及机房咨询 京ICP备13047091号-8