dubbo源码之-ExtensionInjector

news2024/10/7 8:22:15

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<ExtensionInjector> 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> T getInstance(final Class<T> type, final String name) {
        //遍历所有的扩展注入器,如果可以获取到扩展对象则直接返回
        return injectors.stream()
            .map(injector -> injector.getInstance(type, name))
            .filter(Objects::nonNull)
            .findFirst()
            .orElse(null);
    }

SpiExtensionInjector

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库语言一、DDL

&#x1f618;作者简介&#xff1a;正在努力的99年打工人。 &#x1f44a;宣言&#xff1a;人生就是B&#xff08;birth&#xff09;和D&#xff08;death&#xff09;之间的C&#xff08;choise&#xff09;&#xff0c;做好每一个选择。 &#x1f64f;创作不易&#xff0c;动…

华为OD机试真题B卷 JavaScript 实现【分班】,附详细解题思路

一、题目描述 幼儿园两个班的小朋友在排队时混在了一起&#xff0c;每位小朋友都知道自己是否与前面一位小朋友是否同班&#xff0c;请你帮忙把同班的小朋友找出来。 小朋友的编号为整数&#xff0c;与前一位小朋友同班用Y表示&#xff0c;不同班用N表示。 二、输入描述 输…

uniapp/手机APP使用支付宝支付(服务端)

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战、定制、远程&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面…

chatgpt赋能python:Python接口应用于SEO的指南

Python接口应用于SEO的指南 Python成为了web开发中最流行的语言之一&#xff0c;而且尤其在SEO领域中被广泛应用。一些Python库和框架可帮助SEO团队实现其目标&#xff0c;如排名跟踪&#xff0c;爬取数据&#xff0c;进行网站分析&#xff0c;等等。在本文中&#xff0c;我们…

基于Hexo和Butterfly创建个人技术博客,(9) 优化butterfly主题配置文章版本

Butterfly官方网站&#xff0c;请 点击进入 本章目标&#xff1a; 掌握butterfly主题对文章的配置&#xff0c;熟悉并可按需配置到个人的博客站点中&#xff0c;本章内容是一个必会章节&#xff0c;不仅包括文章的UI美化、SEO相关配置还包括其它增加的功能&#xff0c;内容不多…

英语不好能不能学编程?

入门教程、案例源码、学习资料、读者群 请访问&#xff1a; python666.cn 大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; 常有人问我&#xff1a;我英语不好&#xff0c;想学编程行不行&#xff1f; 这个问题需要分情况讨论。 1. 可以学 如果你因为担心自己英语不…

chatgpt赋能python:Python怎么用?Python编程的入门指南

Python怎么用&#xff1f;Python编程的入门指南 Python是一种流行的高级编程语言&#xff0c;它被广泛应用于数据分析、机器学习、Web开发、自动化测试等领域。Python语言非常容易学习和使用&#xff0c;因此非常适合初学者和有经验的开发人员。在这篇文章中&#xff0c;我们将…

手把手教你在CentOS7.9上使用docker 安装MySQL5.7

前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本文主要讲解如何用docker在centos7.9系统上安装MySQL5.7&#xff0c;以及如何设置MySQL的远程登录。 文章收录到【容器管理】和【数据库入门到精通专栏】&#xff0c;此专栏是沐风晓月对linux云计算架构…

chatgpt赋能python:Python怎么清除动点轨迹?

Python怎么清除动点轨迹&#xff1f; 引言 在数据科学和可视化的领域中&#xff0c;动点轨迹是很有用的工具。动点轨迹可以轻松地显示数据点的时间序列&#xff0c;这可以帮助分析者发现有关数据集的有用信息。然而&#xff0c;当轨迹过于密集和复杂时&#xff0c;这种可视化…

Spring Cloud Alibaba - Sentinel源码分析(一)

目录 一、Sentinel核心源码分析 1、Sentinel核心概念 1.1、Node之间的关系 2、Sentinel源码入口 2.0、Sentinel源码启动 2.1、SlotChain解析 2.2、NodeSelectorSlot解析 2.3、ClusterBuilderSlot解析 2.4、StatisticSlot解析 2.5、FlowSlot解析 2.6、DegradeSlot解析…

白鲸优化算法优化VMD参数,最小包络熵为适应度函数,提取最小包络熵对应的IMF分量,采集最佳IMF分量的9种时域指标,提取特征向量。以西储大学数据为例,附MATLAB代码

大家看到这篇文章&#xff0c;肯定会有疑问&#xff0c;难道本篇文章和上一篇文章不是一个意思嘛&#xff0c;这是来凑数的嘛……其实不然&#xff0c;如果各位读者仔细看&#xff0c;就会发现本篇文章和上一篇文章大有不同&#xff0c;这篇文章也是我一直以来想在上一篇文章基…

chatgpt赋能python:Python断言:如何断言等于两个值其中一个?

Python断言&#xff1a;如何断言等于两个值其中一个&#xff1f; Python是一种广泛使用的编程语言&#xff0c;而断言是它的一个重要功能。在编程中&#xff0c;我们可以使用断言来验证代码是否按照预期工作。但是&#xff0c;在某些情况下&#xff0c;我们可能想要断言两个值…

快速上手kettle(四)壶中可以倒出些啥?

快速上手kettle&#xff08;四&#xff09;壶中可以倒出些啥 前言一 、kettle 这壶里能倒出啥&#xff1f;二 、Access输出2.1 Access输出设置2.2 启动转换&#xff0c;查看输出 三 、Excel输出3.1 选择excel扩展名3.2 1 将表中数据分别写入到excel中 四、JSON output4.1 JSON …

常见骨干网络介绍

骨干网络 骨干网络&#xff08;backbone network&#xff09;顾名思义&#xff0c;是深度学习中最核心的网络组成。本文按时间顺序&#xff0c;简要介绍几种影响重大的backbone设计思路&#xff0c;我们或许可以从窥探前人的设计思路中获得启发和灵感。 1.1 AlexNet, 2012 这…

10倍|中科院再传好消息:比英伟达还快,“新技术”实现弯道超车

中科院再传好消息&#xff1a;在光芯片上有了重大突破&#xff0c;李明-祝宁华团队研制出了一款超高集成度光学卷积处理器。 这种方案具有高算力密度、超高的线性扩展性&#xff01; 基于这种技术的&#xff0c;光芯片的性能将再次提升&#xff0c;光芯片是用于AI,如果能变成现…

每日算法(第二十四期)

先来回顾一下上期的问题及答案&#xff1a; 2023年6月15日 「电话号码的字母组合」&#xff08;Letter Combinations of a Phone Number&#xff09;。以下是题目的描述&#xff1a; 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。给出数字到字母的…

记录--前端如何优雅导出多表头xlsx

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 xlsx导出是比较前后端开发过程中都比较常见的一个功能。但传统的二维表格可能很难能满足我们对业务的需求&#xff0c;因为当数据的维度和层次比较多时,二维表格很难以清晰和压缩的方式展现所有的…

macOS Ventura 13.5beta3(22G5048d)发布

系统介绍 黑果魏叔 6 月 16 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.5 开发者预览版 Beta 3 更新&#xff08;内部版本号&#xff1a;22G5048d&#xff09;&#xff0c;本次更新距离上次发布隔了 15 天。 macOS Ventura 带来了台前调度、连续互通相机、Fa…

【Axure 教程】中继器(进阶篇)

一、修改、删除指定行 首先我们还是在 Axure 页面中拖入一个【中继器】&#xff0c;并双击打开&#xff0c;在默认的【矩形】后面加上【修改】和【删除】按钮&#xff1a; 然后我们给修改按钮添加【中继器事件】&#xff0c;选择【更新行】&#xff1a; 可以看到&#xff0c;由…

Axure RP 9 基础教程 元件基础3

11、组合元件 Axure中可以将多个元件组合起来&#xff0c;组合可以被命名&#xff0c;也可以被当成一个元件来进行交互&#xff0c;调整位置和大小等。选中多个元件&#xff0c;在顶部菜单中点击组合图标即可。选中一个组合&#xff0c;点击取消组合&#xff0c;可以就地解散。…