@Import注解的原理

news/2023/12/9 13:20:53

此注解是springboot自动注入的关键注解,所以拿出来单独分析一下。

启动类的run方法跟进去最终找到refresh方法;

这里直接看这个org.springframework.context.support.AbstractApplicationContext#refresh方法即可,它下面有一个方法

invokeBeanFactoryPostProcessors(beanFactory)

此处, 最终调用的是:

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法;

在这里就不做详细的每一步分析了,直接找起作用的代码了。

它下面有一段如下代码:

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

断点可以看到

 在加上代码的注释,此时第一步调用了获取实现BeanDefinitionRegistryPostProcessor的接口的类的方法,可以看到此时只有一个类,即ConfigurationClassPostProcessor类,它是由容器初始化的时候指定加载的bean定义,用来扫描springboot注解配置的相关属性类;

所以此时就会调用其的processConfigBeanDefinitions方法,此方法中有一个

parser.parse(candidates)

最终调用的方法中会有如下代码

// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true)

可以看到,到此处的时候,才会去加载@Import注解,但在此之前程序会扫描@Component、@PropertySources@ComponentScans注解

此时,读取到相应的实现import引入的类的selectImports方法,即可执行相关的配置属性;在执行的时候有一个判断:

if (candidate.isAssignable(ImportSelector.class)) {
}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
}

即使用Import注解时,其类必须实现ImportSelector接口或者ImportBeanDefinitionRegistrar接口;

然后调用其selectImports方法或者registerBeanDefinitions方法,这里ImportSelector还有一个子接口即:DeferredImportSelector接口

那么在这个三者之间存在什么关系?

if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}

如果实现了DeferredImportSelector接口,它会将其放入一个DeferredImportSelectorHandler中,不会立马执行;而如果是ImportSelector接口,则会直接调用其方法。如果是ImportBeanDefinitionRegistrar接口,则会添加到ConfigurationClass#importBeanDefinitionRegistrars属性中,他是一个map。

所以,ImportSelector接口会直接执行方法,其他两种都会延迟执行加载,那么延迟到什么时候呢?

1)对于DeferredImportSelector接口,则是parse方法的最后一步:

this.deferredImportSelectorHandler.process()

此时才会去执行实现ImportBeanDefinitionRegistrar接口的方法;

此时要注意,ImportBeanDefinitionRegistrar接口内部有一个Group接口,当getImportGroup方法不返回null时,此时就不会执行其selectImports接口了,此时会调用Group下的process方法;此处在后面会使用到;

ImportSelectorDeferredImportSelector的区别,就是selectImports方法执行时机有差别,在DeferredImportSelector之前会对@ImportResource、@Bean这些注解进行处理。

2)对于ImportBeanDefinitionRegistrar接口,

在上面的parse方法执行完之后,会有如下方法:

this.reader.loadBeanDefinitions(configClasses)

此时会执行ImportBeanDefinitionRegistrar接口的方法;

所以最终的执行时机为:

ImportSelector接口的优先级高于DeferredImportSelector接口的执行时机;

DeferredImportSelector接口的优先级高于ImportBeanDefinitionRegistrar接口的执行时机。


http://www.ppmy.cn/news/28654.html

相关文章

面试阿里测开岗,被面试官针对,当场翻脸,把我的简历还给我,疑似被拉黑...

好家伙,金三银四一到,这奇葩事可真是多,前两天和粉丝聊天,他说前段时间面试阿里的测开岗,最后和面试官干起来了。 我问他为什么,他说没啥,就觉得面试官太装了,就爱问一些虚而不实的…

QML 鼠标事件

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 QML 中有一些元素本身是不具备交互能力的(例如:Rectangle、Text、Image 等),那么如何通过鼠标来控制它们的行为呢?这里就需要用到 MouseArea 元素了,它继承于 Item 且不可见,通常需要与可见元素结合使…

SE-SSD论文阅读

摘要 本文提出了一种基于自集成单级目标检测器(SE-SSD)的室外点云三维目标检测方法。我们的重点是利用我们的公式约束开发软目标和硬目标来联合优化模型,而不引入额外的计算在推理中。具体来说,SE-SSD包含一对teacher 和student ssd,在其中我…

Java的运算操作

个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录算术运算符增量运算符注意自增自减运算符关系运算符逻辑运算符逻辑与&&逻辑或||逻辑非!…

XGBoost-XGBoost objective 参数部分选项解释

首先 objective 是目标函数的意思,也就是建模的时候,需要最小化的函数 binary:logistic: logistic regression for binary classification, output probability Binary:logistic:二分类逻辑回归,输出标签为 1 概率 binary:logit…

筑基八层 —— 问题思考分析并解决

目录 零:移步 一.修炼必备 二.问题思考(先思考) 三.问题解答 零:移步 CSDN由于我的排版不怎么好看,我的有道云笔记相当的美观,请移步有道云笔记 一.修炼必备 1.入门必备:VS2019社区版&#x…

C/C++每日一练(20230227)

目录 1. 按要求排序数组 ★ 2. Z 字形变换 ★★ 3. 下一个排列 ★★ 1. 按要求排序数组 给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中,数字 1 的数目升序排序。 如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小…

【Node.js】MySQL数据库

数据库数据库的基本概念什么是数据库常见的数据库和分类数据库的数据组织结构实际开发中库,表,行,字段的关系MySQL相关的软件MySQL Workbench创建数据库创建数据表设计表字段字段的特殊标识向表中插入数据使用SQL管理数据库什么是SQLSQL能做什…

ssh远程连接ECS实例连接失败

尝试通过 SSH 远程连接服务来连接ECS云服务器实例时,收到“连接被拒”或“连接超时”的错误信息,可能的原因分析如下: 错误信息描述 1、错误消息:“ssh: connect to ecs-X-X-X-X.compute-xxxxxxxxx.com port 22: Connection tim…

【C++进阶】三、二叉搜索树

目录 一、二叉搜索树 1.1 概念 1.2 二叉搜索树操作 二、二叉搜索树实现 2.1 框架总览 2.2 实现接口总览 2.2.1 构造函数 2.2.2 拷贝构造 2.2.3 赋值重载 2.2.4 析构函数 2.2.5 二叉搜索树的遍历 2.2.6 插入函数 2.2.7 查找函数 2.2.8 删除函数 2.3 二叉搜索数完整…

华为OD机试真题Java实现【快递运输】真题+解题思路+代码(20222023

快递运输 题目 一辆运送快递的货车,运送的快递均放在大小不等的长方体快递盒中,为了能够装载更多的快递,同时不能让货车超载,需要计算最多能装多少个快递。 注:快递的体积不受限制,快递数最多1000个,货车载重最大50000。 🔥🔥🔥🔥🔥👉👉👉👉👉�…

【Linux】Linux根文件系统扩容

场景:根文件系统需要至少100GB的剩余空间,但是目前就剩余91GB。因此,我们需要对根文件系统进行扩容。# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs …

27K测试老鸟分享自己6年面试心得,四种公司、四种问题…

这里总结了下自己今年的面试情况 先说一下自己的个人情况,普通二本计算机专业毕业,懂python,会写脚本,会selenium,会性能。趁着金三银四跳槽季,面试字节跳动测试岗技术面都已经过了,本来以为是…

TCP协议原理三

文章目录七、延时应答八、捎带应答九、面向字节流粘包问题十、TCP异常情况总结七、延时应答 如果说滑动窗口的关键是让窗口大一些,传输速度就快一些。那么延时应答就是在接收方能够处理的前提下,尽可能把ack返回的窗口大小尽可能大一些。 如果在接受数据…

【Linux】网卡的7种bond模式

网卡的7种bond模式 一、bond模式 Mode0(balance-rr) 表示负载分担round-robin,和交换机的聚合强制不协商的方式配合 Mode1(active-backup) 表示主备模式,只有一块网卡是active,另外一块是备的standby,这时如果交换机配的是捆绑&#xff0c…

〖大前端 - 基础入门三大核心篇②〗- 前端开发工具和环境准备

大家好,我是 哈士奇 ,一位工作了十年的"技术混子", 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 💬 人生格言:优于别人,并不高贵,真正的高贵应该是优于过去的自己。💬 &#x1f4e…

认识STM32和如何构建STM32工程

STM32介绍什么是单片机单片机(Single-Chip Microcomputer)是一种集成电路芯片,把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种/0口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电…

【基础算法】哈希表(开放寻址法)

🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…

Redis 主从库如何实现数据一致?

目录 1、主从库间如何进行第一次同步? 2、主从级联模式分担全量复制时的主库压力 3、主从库间网络断了怎么办? 总结 // 好的文章,值得反复去读 Redis 具有高可靠性,这里有两层含义:一是数据尽量少丢失,…

Java编程问题top100---基础语法系列(一)

Java编程问题top100---基础语法系列一一、Java 操作符实质二、将InputStream转换为String使用IOUtils自己写轮子三、将数组转换为List四、如何遍历map对象使用For-Each迭代entries(方法一)使用For-Each迭代keys和values(方法二)使…
最新文章