当前位置: 首页 > news >正文

SpringBoot自动装配原理之@Import注解解析

文章目录

  • 1. 概述
  • 2. 使用
    • 2.1 导入普通Bean
    • 2.2 导入配置类
    • 2.3 导入 ImportSelector 实现类
    • 2.4 导入 ImportBeanDefinitionRegistrar 实现类
  • 3. 区别


在这里插入图片描述

在这里插入图片描述


1. 概述

当谈及现代Java开发领域中的框架选择时,SpringBoot无疑是无与伦比的热门之选。其简化了开发流程,提高了效率,同时保持了可靠性和可维护性。在这个充满活力的生态系统中,@Import注解闪耀着独特的光芒。它不仅仅是一个普通的注解,更是一个强大的工具,为我们提供了一种优雅而灵活的方式来管理组件的装配和配置。本文将带您深入探究@Import注解的内涵,揭示其背后的原理和机制,助您在SpringBoot项目中游刃有余地应用这一技术,从而让您的应用更加强大、灵活和易于扩展。让我们一起踏上这场关于@Import注解的探索之旅,探索其奥秘,挖掘其潜力!


Spring 提供的@Import 注解: 使用@Import导入的类会被Spring加载到 IOC 容器中, 有四种用法:

  1. 导入Bean
  2. 导入配置类
  3. 导入 ImportSelector 实现类。一般用于加载配置文件中的类
  4. 导入 ImportBeanDefinitionRegistrar 实现类

2. 使用

2.1 导入普通Bean

会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径

构造一个类

public class User {private Integer id;private String name;//	get set 略@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}

使用第一种方式导入

package com.snow;import com.snow.po.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;@Import(User.class)//会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
@SpringBootApplication
public class TempApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(TempApplication.class, args);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();// 获取并使用每个beanfor (String beanName : beanDefinitionNames) {Object bean = applicationContext.getBean(beanName);System.out.println("Bean: " + beanName + " - " + bean.getClass().getName());// 在这里可以进行进一步的操作}// 关闭应用程序上下文applicationContext.close();}
}

执行结果如下:
在这里插入图片描述

可以看到 User 类被注入了容器.


2.2 导入配置类

创建 MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称

定义一个类

public class Student {private Integer id;private String name;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}

创建配置类

@Configuration
public class MyConfig {@Beanpublic Student student() {return new Student();}}

第二种方式注入

//@Import(User.class)//会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
@Import(MyConfig.class) //  创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
@SpringBootApplication
public class TempApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(TempApplication.class, args);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();// 获取并使用每个beanfor (String beanName : beanDefinitionNames) {Object bean = applicationContext.getBean(beanName);System.out.println("Bean: " + beanName + " - " + bean.getClass().getName());// 在这里可以进行进一步的操作}// 关闭应用程序上下文applicationContext.close();}
}

执行并查看结果:
在这里插入图片描述
可以看到注入进来了配置类本身及其配置类里面声明的bean.


2.3 导入 ImportSelector 实现类

@ImportSelector 是 Spring 框架提供的一个接口,用于动态地选择需要导入的配置类。通过实现该接口,可以根据特定的条件在运行时选择性地导入一组配置类,从而实现更加灵活的配置管理。

具体来说,@ImportSelector 接口定义了一个方法 selectImports(),该方法返回一个字符串数组,数组中包含需要导入的配置类的全限定类名。当在 Spring 配置类中使用 @Import 注解并指定实现了 @ImportSelector 接口的类时,Spring 在加载配置类时会调用该类的 selectImports() 方法,根据方法返回的配置类的全限定类名来加载相应的配置类。

使用 @ImportSelector 的主要优势在于可以根据程序运行时的条件来动态地选择性地导入配置类,从而实现更加灵活的组件管理和配置。例如,可以根据环境变量、配置文件的内容或者其他动态条件来决定需要加载哪些配置类,从而实现不同环境下的定制化配置。

定义一个类

public class Teacher {private Integer id;private String name;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}

编写 ImportSelector 的实现类: MyImportSelector如下:

public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {//	返回类的全路径的字符串数组return new String[]{"com.snow.po.Teacher"};}
}

第三张方式注入

//@Import(User.class)//会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
//@Import(MyConfig.class) //  创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
@Import(MyImportSelector.class) // 会调用 MyImportSelector 类的 selectImports() 方法,该方法返回一个类名称的数组,Spring 将加载这些类,这样它们的配置信息就可以被应用到当前的上下文中。
@SpringBootApplication
public class TempApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(TempApplication.class, args);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();// 获取并使用每个beanfor (String beanName : beanDefinitionNames) {Object bean = applicationContext.getBean(beanName);System.out.println("Bean: " + beanName + " - " + bean.getClass().getName());// 在这里可以进行进一步的操作}// 关闭应用程序上下文applicationContext.close();}
}

执行并看结果:
在这里插入图片描述

注意: 这种方式是最重要的, SpringBoot自动装配核心使用了这种方式自动注入大量Bean.


2.4 导入 ImportBeanDefinitionRegistrar 实现类

导入 ImportBeanDefinitionRegistrar 实现类的作用是允许在 Spring 应用程序上下文加载时以编程方式注册额外的 bean 定义。与 ImportSelector 类似,ImportBeanDefinitionRegistrar 接口也提供了一种动态注册 bean 定义的机制,但是它更加灵活,可以在注册过程中对 bean 定义进行更复杂的操作。

当你使用 @Import 注解导入实现了 ImportBeanDefinitionRegistrar 接口的类时,Spring 在加载配置类时会调用该类的 registerBeanDefinitions() 方法。在这个方法中,你可以通过编程方式注册 bean 定义,包括指定 bean 的名称、类型、作用域以及其他属性。

通过使用 ImportBeanDefinitionRegistrar,你可以在运行时根据需要动态地注册 bean,这样可以更灵活地管理和配置 Spring 应用程序的组件。这种机制特别适用于需要根据外部条件或者动态变化的情况下注册 bean 的场景,例如基于配置文件或者运行时环境来决定需要注册哪些 bean。

定义一个类

public class School {private Integer id;private String name;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}

实现ImportBeanDefinitionRegistrar 接口

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** @param importingClassMetadata 导入类的元注解信息* @param registry Bean注册表*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(School.class).getBeanDefinition();registry.registerBeanDefinition("school", beanDefinition);}}

第四种方式导入

@Import(MyImportBeanDefinitionRegistrar.class)
@SpringBootApplication
public class TempApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(TempApplication.class, args);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();// 获取并使用每个beanfor (String beanName : beanDefinitionNames) {Object bean = applicationContext.getBean(beanName);System.out.println("Bean: " + beanName + " - " + bean.getClass().getName());// 在这里可以进行进一步的操作}// 关闭应用程序上下文applicationContext.close();}
}

执行看结果
在这里插入图片描述

可以看到注册成功.


3. 区别

@Import(MyImportSelector.class) 和 @Import(MyImportBeanDefinitionRegistrar.class) 都是用于在 Spring 中动态导入配置信息的注解,但它们的作用和使用场景略有不同。

  1. @Import(MyImportSelector.class):

    • 作用:通过实现 ImportSelector 接口的类,动态地选择需要导入的配置类。
    • 使用场景:通常用于根据某些条件动态地选择需要导入的配置类。例如,根据环境变量或者配置文件中的设置来决定需要加载哪些组件或配置。
  2. @Import(MyImportBeanDefinitionRegistrar.class):

    • 作用:通过实现 ImportBeanDefinitionRegistrar 接口的类,以编程方式注册额外的 bean 定义。
    • 使用场景:通常用于需要根据运行时动态条件注册 bean 的场景。例如,根据系统配置或者运行时环境来决定需要注册哪些 bean,或者根据一些复杂的逻辑来注册 bean。

使用场景示例:

如果需要根据一些条件在运行时动态地选择性地加载一些配置类,可以使用@Import(MyImportSelector.class)。

如果需要在运行时根据条件注册一些 bean,可能需要进行一些复杂的逻辑判断,并且注册的 bean 可能不只是简单地选择性加载配置类,你可以使用 @Import(MyImportBeanDefinitionRegistrar.class)。





在这里插入图片描述



相关文章:

SpringBoot自动装配原理之@Import注解解析

文章目录 1. 概述2. 使用2.1 导入普通Bean2.2 导入配置类2.3 导入 ImportSelector 实现类2.4 导入 ImportBeanDefinitionRegistrar 实现类 3. 区别 1. 概述 当谈及现代Java开发领域中的框架选择时,SpringBoot无疑是无与伦比的热门之选。其简化了开发流程&#xff0…...

49 样式迁移【李沐动手学深度学习v2课程笔记】

1. 样式迁移(Style Transfer) 计算机视觉的应用之一,将样式图片中的样式(比如油画风格等)迁移到内容图片(比如实拍的图片)上,得到合成图片 可以理解成为一个滤镜,但相对于滤镜来讲…...

Linux的学习之路:4、权限

一、Linux权限的概念 权限我们都熟悉,最常见的就是在看电视时需要vip这个就是权限,然后在Linux就是有两个权限,就是管理员也就是超级用户和普通的用户 命令:su [用户名] 功能:切换用户。 例如,要从root用户…...

自定义类型—结构体

目录 1 . 结构体类型的声明 1.1 结构的声明 1.2 结构体变量的创建与初始化 1.3 结构体的特殊声明 1.4 结构体的自引用 2. 结构体内存对齐 2.1 对齐规则 2.2 为什么存在内存对齐 2.3 修改默认对齐数 3. 结构体传参 4.结构体实现位段 4.1 位段的内存分配 4.3 位段的…...

【JavaWeb】Jsp基本教程

目录 JSP概述作用一个简单的案例:使用JSP页面输出当前日期 JSP处理过程JSP 生命周期编译阶段初始化阶段执行阶段销毁阶段案例 JSP页面的元素JSP指令JSP中的page指令Include指令示例 taglib指令 JSP中的小脚本与表达式JSP中的声明JSP中的注释HTML的注释JSP注释 JSP行…...

外包干了25天,技术退步明显.......

先说一下自己的情况,大专生,18年通过校招进入杭州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…...

C++(14): STL条件变量std::condition_variable

1. 简述 在C的标准模板库(STL)中,std::condition_variable是一个非常重要的同步原语,用于在多线程编程中实现线程间的条件同步。它允许一个或多个线程等待某个条件成立,当条件成立时,等待的线程会被唤醒并继…...

Harmony与Android项目结构对比

主要文件对应 Android文件HarmonyOS文件清单文件AndroidManifest.xmlmodule.json5Activity/Fragmententryability下的ts文件XML布局pages下的ets文件resresourcesModule下的build.gradleModule下的build-profile.json5gradlehvigor根目录下的build.gradle根目录下的build-profi…...

langchain 学习笔记-FunctionCalling三种方式

ChatGPT 基于海量的训练数据生成答案,所以它无法回答训练数据中没有的信息或搜索信息 。人们希望 ChatGPT 具有对话以外的各种功能,例如“我想管理我的待办事项列表”。 函数调用是对此类请求的响应。 通过使用函数调用,ChatGPT 现在可以在生…...

CNAS软件测试公司有什么好处?如何选择靠谱的软件测试公司?

CNAS认可是中国合格评定国家认可委员会的英文缩写,由国家认证认可监督管理委员会批准设立并授权的国家认可机构,统一负责对认证机构、实验室和检验机构等相关机构的认可工作。 在软件测试行业,CNAS认可具有重要意义。它标志着一个软件测试公…...

Cohere推出全新升级版RAG大型AI模型:支持中文,搭载1040亿参数,现开源其权重!

4月5日,知名类ChatGPT平台Cohere在其官方网站上发布了一款全新的模型——Command R。 据官方消息,Command R拥有1040亿个参数,并且支持包括英语、中文、法语、德语在内的10种语言。这一模型的显著特点之一在于其对内置的RAG(检索增…...

搭建前后端的链接(java)

搭建前后端的链接(java) 一.前提 1.1 javaEE 搭建前后端的链接首先需要用到javaEE,也就是java企业版,也就是java后端(后端javaSE) 利用javaEE和前端交互,javaSE和数据库交互,javaSE和javaEE之间再进行交互就实现了前后端的交互…...

Java多路查找树(含面试大厂题和源码)

多路查找树(Multiway Search Tree),也称为B树或B树,是一种自平衡的树形数据结构,用于存储大量数据,通常用于数据库和文件系统中。它允许在查找、插入和删除操作中保持数据的有序性,同时优化了磁…...

day6 | 哈希表 part-2 | 454 四数相加II 、383. 赎金信、15. 三数之和、18. 四数之和

今日任务 454 四数相加II (题目: . - 力扣(LeetCode))383 赎金信 (题目: . - 力扣(LeetCode)) 454 四数相加II 题目:. - 力扣(LeetCode) 给你四个整数数组 nums1、num…...

Redis常见数据类型(2)

目录 String字符串 常见命令 SET GET MGET MSET SETNX 计数命令 INCR INCRBY DECR DECRBY INCRFLOAT 其它命令 APPEND GETRANGE SETRANGE STRLEN String字符串 字符串是Redis最基础的数据类型, 关于字符串需要特别注意: (1)首先Redis中所有的键的类型都是字符…...

SparkBug解决:Type mismatch; found : org.apache.spark.sql.Column required: Double

def assginFlag(aizmuth:Double):Option[Int] {val interval 0.5val index (aizmuth / interval ).toIntif (index > 0 && index < 720 ) Some(index 1) else None} assginFlag方法中的条件判断条件 (index > 0 && index < 720) 返回的是一个布…...

MQ之————如何保证消息的可靠性

MQ之保证消息的可靠性 1.消费端消息可靠性保证&#xff1a; 1.1 消息确认&#xff08;Acknowledgements&#xff09;&#xff1a; 消费者在接收到消息后&#xff0c;默认情况下RabbitMQ会自动确认消息&#xff08;autoAcktrue&#xff09;。为保证消息可靠性&#xff0c;可以…...

TrollInstallerX官方一键安装巨魔商店

TrollInstallerX是巨魔官方开发的一款一键巨魔商店安装器&#xff0c;完美支持iOS 14.0 – 16.6.1的设备&#xff0c;操作非常简单&#xff0c;TrollInstallerX依然有个小小的限制&#xff0c;部分机型&#xff0c;还是要采用间接安装方法。 一&#xff0c;直接安装方法 通过…...

生成随机图片验证码

随着互联网的不断发展&#xff0c;安全性问题日益突出。为了保障用户账号的安全性&#xff0c;很多网站都引入了验证码机制。验证码是一种区分用户是计算机还是人的公共全自动程序&#xff0c;可以有效防止恶意攻击和自动化脚本的滥用。本文将介绍如何使用Python生成随机图片验…...

【0280】《数据库系统概论》阅读总结(附xmind思维导图)

0. 阅读进展 选择性地读取了《数据库系统概论》一书中的第13、14章节&#xff0c;并对这两章节中较为重点的内容作了总结和归纳&#xff1b;然后以xmind导图形式给出。 1. xmind思维导图 Xmind附件&#xff1a;...

运算放大器增益带宽积(GBW)计算指南:从原理到选型实战

1. 项目概述&#xff1a;为什么我们需要关心运放的GBW&#xff1f;在模拟电路设计&#xff0c;尤其是信号调理、滤波、放大等前端电路的设计中&#xff0c;运算放大器&#xff08;运放&#xff09;的选择是决定电路性能上限的关键一步。很多工程师在选型时&#xff0c;会重点关…...

088、机器人动力学:牛顿-欧拉法

机器人动力学:牛顿-欧拉法 从一次机械臂抖动说起 去年调试一台六轴协作机器人,空载运行还算平稳,一夹持3kg负载做高速圆弧插补,末端就开始高频抖动。PID参数调了三轮,陷波滤波器加了两个,效果都不理想。后来拆开关节看,发现电机电流波形在加减速阶段有明显的毛刺——这…...

观察Taotoken在多日连续调用中的延迟与稳定性表现

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 观察Taotoken在多日连续调用中的延迟与稳定性表现 在需要连续多日、高频率调用大模型API的场景中&#xff0c;例如持续性的内容生成…...

QuickBMS深度剖析:游戏资源提取的终极解决方案与实战指南

QuickBMS深度剖析&#xff1a;游戏资源提取的终极解决方案与实战指南 【免费下载链接】QuickBMS QuickBMS by aluigi - Github Mirror 项目地址: https://gitcode.com/gh_mirrors/qui/QuickBMS QuickBMS是一款强大的开源游戏资源处理引擎&#xff0c;专为游戏开发者、逆…...

从‘点一下’到‘连一连’:Qt6中PushButton信号与槽的5种连接方式详解(含Lambda表达式实战)

从‘点一下’到‘连一连’&#xff1a;Qt6中PushButton信号与槽的5种连接方式详解&#xff08;含Lambda表达式实战&#xff09; 在Qt框架中&#xff0c;PushButton作为最基础的交互控件之一&#xff0c;其信号与槽机制是构建响应式用户界面的核心。随着Qt6的发布&#xff0c;信…...

Windows 10/11打印服务总罢工?别急着重装,试试这几招修复Print Spooler自动停止

Windows 10/11打印服务罢工&#xff1f;5种专业修复方案拯救Print Spooler 办公室里最令人抓狂的时刻之一&#xff0c;就是当你急需打印文件时&#xff0c;发现打印机毫无反应。你检查服务管理器&#xff0c;发现那个关键的Print Spooler服务又自动停止了。这种情况在Windows …...

基于多模态大模型的智能家居视觉分析:HA-LLMVision部署与应用

1. 项目概述&#xff1a;当智能家居遇上多模态大模型 最近在折腾智能家居的朋友&#xff0c;估计都绕不开一个核心痛点&#xff1a;家里的摄像头、传感器越来越多&#xff0c;但它们的“智商”似乎总差那么一口气。摄像头能告诉你“检测到移动”&#xff0c;但分不清是猫、是人…...

开源大模型适配器Basaran:一键兼容OpenAI API,无缝集成私有化部署

1. 项目概述&#xff1a;当开源大模型遇上“文本补全”接口 如果你最近在折腾开源的大型语言模型&#xff08;LLM&#xff09;&#xff0c;比如 LLaMA、Falcon 或者国内的 ChatGLM、Qwen 系列&#xff0c;你肯定遇到过这样的场景&#xff1a;模型本身能力很强&#xff0c;但它…...

基于容器化与微服务架构的无限路由器:云原生网络控制平台实践

1. 项目概述&#xff1a;一个“无限”路由器的诞生最近在折腾家庭网络和边缘计算项目时&#xff0c;我遇到了一个经典难题&#xff1a;如何在资源受限的硬件上&#xff0c;实现一个功能强大、可扩展且易于管理的网络路由与策略中心&#xff1f;市面上的成品路由器固件&#xff…...

Laravel集成DeepSeek AI:官方SDK配置与实战指南

1. 项目概述与核心价值最近在折腾一个AI相关的Laravel项目&#xff0c;需要集成一个靠谱的文本生成模型。市面上大模型API不少&#xff0c;但要么贵&#xff0c;要么不稳定&#xff0c;要么就是国内访问延迟感人。直到我发现了deepseek-php/deepseek-laravel这个包&#xff0c;…...