@Import原理与实战

文章目录

  • 前言
  • 一、导入普通类
  • 二、导入ImportSelector实现类
  • 三、导入ImportBeanDefinitionRegistrar实现类
  • 四、@Import注解的解析
    • 4.1、解析实现ImportSelector的候选bean
    • 4.2、解析实现ImportBeanDefinitionRegistrar的候选bean
    • 4.3、DeferredImportSelector的特殊处理
  • 总结


前言

  @Import是Spring框架提供的一个核心注解,主要用于在配置类中引入其他配置类或组件。通过在类上标注@Import注解,可以将其value属性中指定的类注册到Spring容器中,从而实现配置的模块化和灵活组合。

一、导入普通类

  @Import注解会将其中导入的普通类,注册成bean放入到Spring容器中。

public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);System.out.println(context.getBean(MyService.class));}
}class MyService {
}@Configuration
@Import(MyService.class) 
class Config {}

  运行结果:

com.itbaima.importdemo.demo1.MyService@55183b20

二、导入ImportSelector实现类

  解析@Import注解时会执行实现了ImportSelector的类的selectImports方法,将返回的数组中的类注册成bean。

public class Demo2 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config1.class);System.out.println(context.getBean(MyService.class));}
}@Configuration
@Import(MyImport.class)
class Config1{}class MyImport implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.itbaima.importdemo.demo1.MyService"};}
}

  运行结果

com.itbaima.importdemo.demo1.MyService@33d512c1

三、导入ImportBeanDefinitionRegistrar实现类

  实现了ImportBeanDefinitionRegistrar的类,可以自己注册bean定义,以及从已有的bean定义中获取指定的bean,进行修改,自由度是最高的。

public class Demo3 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);System.out.println(context.getBean("orderService"));}
}@Configuration
@Import({MyBeanDefinitionRegistrar.class})
class Config {
}class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {GenericBeanDefinition bd = new GenericBeanDefinition();bd.setBeanClass(MyService.class);registry.registerBeanDefinition("orderService", bd);}
}class MyService {
}

  运行结果:

com.itbaima.importdemo.demo2.MyService@2f9f7dcf

四、@Import注解的解析

  @Import注解的解析,体现在refresh方法中的invokeBeanFactoryPostProcessors(调用所有bean工厂后置处理器)这一步:
在这里插入图片描述
  ConfigurationClassPostProcessor,用于配置类的解析:
在这里插入图片描述
  在org.springframework.context.annotation.ConfigurationClassParserprocessImports中完成对于@Import注解的解析:
在这里插入图片描述

4.1、解析实现ImportSelector的候选bean

  对于候选bean实现了ImportSelector接口的处理:

  1. 利用JVM的类加载机制,对于候选bean进行加载。
  2. 使用Spring提供的工具方法instantiateClass反射创建这个ImportSelector实例,并注入必要的环境参数。
  3. 如果候选bean实现了DeferredImportSelector,则将其加入deferredImportSelectors的集合中,延迟处理
  4. 候选bean实现的是ImportSelector接口,就调用目标类重写的selectImports方法,决定要导入哪些类名。然后把类名数组转换成 SourceClass 的集合,并应用排除过滤器。

在这里插入图片描述
  调用目标类重写的selectImports方法,传入的参数就是加入了@Configuration注解的配置类的元信息。最后一步递归调用processImports方法很关键:假设当前第一次调用processImports方法,解析出的类路径是com.itbaima.importdemo.demo1.MyService,那么在递归调用processImports方法时,再次进入
在这里插入图片描述
  循环中进行解析时,由于MyService没有实现ImportSelectorImportBeanDefinitionRegistrar注解,就会进入最后的else分支:(@Import导入的普通bean,进入的也是该分支)
在这里插入图片描述
  在最后的else分支中,还会去递归调用processConfigurationClass,将MyService当做配置类去解析,最终将解析完成的放入到ConfigurationClass的集合中。(注意,通过Import解析出的类路径下的bean,bean名称为空,后续需要再次进行处理。)
在这里插入图片描述
  this.reader.loadBeanDefinitions(configClasses);这一步,会对于@Import导入的普通bean进行处理:
在这里插入图片描述
  生成一个beanName,并且将bean定义注册到bean工厂中:
在这里插入图片描述

4.2、解析实现ImportBeanDefinitionRegistrar的候选bean

  @Import导入实现ImportBeanDefinitionRegistrar的候选bean的解析逻辑,在else…if的分支中,同样是通过JVM的类加载机制,加载候选类的class类,然后使用Spring提供的工具方法instantiateClass反射创建这个ImportBeanDefinitionRegistrar实例,并注入必要的环境参数。
在这里插入图片描述
  最后将其加入到ConfigurationClassimportBeanDefinitionRegistrars属性中:
在这里插入图片描述
  它的解析同样是在processConfigBeanDefinitionsthis.reader.loadBeanDefinitions(configClasses);中:
在这里插入图片描述
  回调用户重写的registerBeanDefinitions的逻辑。
在这里插入图片描述

4.3、DeferredImportSelector的特殊处理

  用户实现ImportSelector时,有一种特殊的情况,即用户实现了DeferredImportSelectorDeferredImportSelectorImportSelector的子类。在该分支中,仅仅是先将其加入DeferredImportSelectorHandlerdeferredImportSelectors属性中:
在这里插入图片描述
  DeferredImportSelectorHandlerdeferredImportSelectors属性是一个集合:
在这里插入图片描述
  最终会在所有bean解析完成后再去进行解析:
在这里插入图片描述
  该机制主要应用于Spring Boot的自动配置场景,其核心作用是确保用户自定义的Bean能够优先于自动配置的Bean执行。由于spring.factories中定义的自动配置Bean通常采用条件装配机制,当容器中已存在用户自定义的同类型Bean时,系统将不再重复装配。这正是通过@Bean注解添加的Bean能够覆盖默认Bean的原因
在这里插入图片描述
在这里插入图片描述
  在doProcessConfigurationClass中,默认的@Bean的注解,是后于@Import注解解析的。如果你不显式允许覆盖,Spring 在注册 BeanDefinition 时会抛出异常或者忽略重复的注册。
在这里插入图片描述
  但是对于DeferredImportSelector的解析,是在doProcessConfigurationClass的外层parse方法中执行的,后于@Bean注解的解析。

总结

  @Import注解是为了替换掉配置文件中的import标签,主要是为了导入第三方的配置类,除此之外:

  1. 可以在配置类中指定@Import注解,将其中的类注入到容器中。
  2. 可以在配置类中指定@Import注解,同时其中的类实现了Import Selector接口,会执行重写的selectImports方法,并且将其中指定的路径的对象注入到容器中。
  3. 如果导入的类型实现了Import BeanDefinitionRegistrar,则可以自己注册 BeanDefinition,自由度更高。

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

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

相关文章

day 18进行聚类,进而推断出每个簇的实际含义

浙大疏锦行 对聚类的结果根据具体的特征进行解释,进而推断出每个簇的实际含义 两种思路: 你最开始聚类的时候,就选择了你想最后用来确定簇含义的特征, 最开始用全部特征来聚类,把其余特征作为 x,聚类得到…

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…

iview组件库:当后台返回到的数据与使用官网组件指定的字段不匹配时,进行修改某个属性名再将response数据渲染到页面上的处理

1、需求导入 当存在前端需要的数据的字段渲染到表格或者是一些公共的表格组件展示数据时的某个字段名与后台返回的字段不一致时,那么需要前端进行稍加处理,而不能直接this.list res.data;这样数据是渲染不出来的。 2、后台返回的数据类型 Datalist(pn) …

Ubuntu下有关UDP网络通信的指令

1、查看防火墙状态: sudo ufw status # Ubuntu 2、 检查系统全局广播设置 # 查看是否忽略广播包(0表示接收,1表示忽略) sysctl net.ipv4.icmp_echo_ignore_broadcasts# 查看是否允许广播转发(1表示允许&#xff09…

vue3:十六、个人中心-修改密码

一、页面效果 页面展示当前用户名(只读),展示需要输入的当前密码,输入新的密码以及确认密码的提交表单 二、初始建立 1、建立密码修改页面 在个人中心文件夹中写入新页面UpdatepwdView.vue 2、新建路由 在路由页面中写入修改密码页面 3、新建菜单 在菜单布局菜单页面中写…

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…

【Vue3】(三)vue3中的pinia状态管理、组件通信

目录 一、vue3的pinia 二、【props】传参 三、【自定义事件】传参 四、【mitt】传参 五、【v-model】传参(平常基本不写) 六、【$attrs】传参 七、【$refs和$parent】传参 八、provide和inject 一、vue3的pinia 1、什么是pinia? pinia …

【DAY43】复习日

内容来自浙大疏锦行python打卡训练营 浙大疏锦行 作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 进阶:并拆分成多个文件

xtp+ctp 交易系统接口简介

CTP(上海期货交易所综合交易平台)和 XTP(中泰证券极速交易平台)是中国金融市场中两个重要的证券期货交易系统,它们在定位、架构和应用场景上有显著区别: 1. 开发主体与服务领域 维度CTPXTP开发公司上海期货…

阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】

个人记录 进入控制台,找到定时与自动化任务 进入‘安装/卸载扩展程序’ 点击‘安装扩展程序’ 选择docker社区版,点击下一步与确定,等待一会 安装成功 查询版本 查询docker sudo docker version查询docker compose sudo docker compo…

非Root用户启动SSH服务经验小结

各位看官,小子我先问个问题:是不是经常在容器里想开个SSH,却发现自己不是root,处处碰壁?这是常态。多数容器镜像精简到连SSH服务都没有,就算有,咱们普通用户也没权限启动它。 今天小子就介绍一…

Windows开机自动启动中间件

WinSW(Windows Service Wrapper 是一个开源的 Windows 服务包装器,它可以帮助你将应用程序打包成系统服务,并实现开机自启动的功能。 一、下载 WinSW 下载 WinSW-x64.exe v2.12.0 (⬇️ 更多版本下载) 和 sample-minimal.xml 二、配置 WinS…

【CATIA的二次开发23】抽象对象Document涉及文档激活控制的方法

在CATIA VBA开发中,Document对象是最核心、最基础的对象之一。它代表了当前在CATIA会话中打开的一个文档(文件)。 几乎所有与文件操作、模型访问相关的操作都始于获取一个Document对象。Document对象包含多种方法和属性,以下介绍Document对象方法和属性 一、Document对象方…

基于多维视角的大模型提升认知医疗过程层次激励编程分析

系统架构设计 #mermaid-svg-k3W5lvie1sP3T956 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-k3W5lvie1sP3T956 .error-icon{fill:#552222;}#mermaid-svg-k3W5lvie1sP3T956 .error-text{fill:#552222;stroke:#55222…

【评测】Qwen3-Embedding模型初体验

回到目录 【评测】Qwen3-Embedding模型初体验 模型的介绍页面 0.6B运行配置:笔记本i5-8265U,16G内存,无GPU核显运行,win10操作系统 8B运行配置:AMD8700G,64G内存,4090D 24G显存,ub…

MPLAB X IDE ​软件安装与卸载

1、下载MPLAB X IDE V6.25 MPLAB X IDE | Microchip Technology 正常选Windows,点击Download,等待自动下载完成; MPLAB X IDE 一台电脑上可以安装多个版本; 2、安装MPLAB X IDE V6.25 右键以管理员运行;next; 勾选 I a…

PLC入门【2】PLC的接线

02 PLC的接线 PLC 的品牌介绍,PLC的接线 1、PLC 大体分为欧式和日式 2、只要学会三菱的,整个日式的也差不多会了。 3、PLC 分为晶体管输出和继电器输出。 4、PLC 接线都差不多的 我们主要是讲这个三菱的 PLC, 三菱和台达的 PLC,…

Hibernate Validator 数据验证

Hibernate Validator不仅可以用于Controller层的参数验证,还可以在Service层、Repository层或任何其他层中使用。 手动验证 在任何地方都可以通过Validator接口手动触发验证: public class ManualValidationExample {public void validateObject(Obje…

【深度学习】表示学习:深度学习的数据解构与重构艺术

作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程,深度学习领域研究生必读教材),开始深度学习领域学习,深入全面的理解深度学习的理论知识。 之前的文章参考下面的链接&#xf…

如何在PowerBI中使用Analyze in Excel

如何在PowerBI中使用Analyze in Excel 之前分享过如何使用DAXStudio将PowerBI与Excel连接 ,今天介绍另外一个工具,也可以实现同样的功能,Analyze in Excel。 使用Analyze in Excel 第一步: 首先准备好一个PBIX文件&#xff0c…