SpringBoot自动装配原理、条件注解及封装Starter

news2024/10/5 15:28:54

1.什么是 SpringBoot 自动装配?

我们现在提到自动装配的时候,一般会和Spring Boot联系在一起。但是实际上SpringFramework 早就实现了这个功能。Spring Boot 只是在其基础上,通过 SPI 的方式,做了进一步优化。
SpringBoot 定义了一套接口规范:
SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。
没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。

<dependency>     
    <groupId>org.springframework.boot</groupId>    
    <artifactId>spring-boot-starter-data-redis</artifactId> 
</dependency> 

引入 starter 之后,我们通过少量注解和一些简单的配置就能使用第三方组件提供的功能了。

2.SpringBoot 是如何实现自动装配的?

依赖SpringBoot的核心注解实现 @SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    xxxx
}

其中@EnableAutoConfiguration 是实现自动装配的重要注解,我们以这个注解入手。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
xxx
}

可以看到自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector
那我们继续分析下AutoConfigurationImportSelector 类到底做了什么?
在这里插入图片描述

AutoConfigurationImportSelector:加载自动装配类

可以看到他是实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 判断自动装配开关是否打开 默认是开启
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        // 获取获取所有需要装配的bean
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

我们在继续看getAutoConfigurationEntry 方法是如何获取装配bean的

/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
    return EMPTY_ENTRY;
}
// 获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取装配Bean
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 过滤重复bean
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
// 移除需要排除的bean
configurations.removeAll(exclusions);
// 根据AutoConfigurationImportFilter的match方法来判断是否符合OnBeanCondition,OnClassCondition,OnWebApplicationCondition 过滤bean
configurations = getConfigurationClassFilter().filter(configurations);
// 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}

其中getCandidateConfigurationsgetConfigurationClassFilter().filter 方法为核心
getCandidateConfigurations 获取配置bean ,如图所示
在这里插入图片描述
主要调用 org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
再调用 org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories如图所示
其原理就是读取META-INF/spring.factories文件的的URL
在这里插入图片描述
getConfigurationClassFilter().filter 方法用于根据AutoConfigurationImportFilter的match方法来判断是否符合OnBeanCondition,OnClassCondition,OnWebApplicationCondition 过滤bean 如图所示
在这里插入图片描述
最后,总结下SpringBoot自动配置的原理,主要做了以下事情:

  1. spring.factories配置文件中加载自动配置类,利用org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories 方法实现
  2. 加载的自动配置类中排除掉@EnableAutoConfiguration注解的exclude属性指定的自动配置类;
  3. 再用AutoConfigurationImportFilter接口去过滤自动配置类是否符合其标注注解
    OnBeanCondition(如:ConditionalOnBean、ConditionalOnMissingBean)、OnClassCondition(如:ConditionalOnClass、ConditionalOnMissingClass)、OnWebApplicationCondition(如ConditionalOnWebApplication、ConditionalOnNotWebApplication)的条件,若都符合的话则返回匹配结果;
  4. 触发AutoConfigurationImportEvent事件
  5. 最后spring再将最后筛选后的自动配置类导入IOC容器中

拓展
1.条件注解
@ConditionalOnBean:当容器里有指定 Bean 的条件下
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下没有指定类的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件
@ConditionalOnJava:基于 Java 版本作为判断条件
@ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
@ConditionalOnWebApplication:当前项目是 Web 项 目的条件下
2.控制自动装配顺序注解
@AutoConfigureOrder
@AutoConfigureBefore
@AutoConfigureAfter
@AutoConfiguration(after = xx.class, before = xx.class)
@AutoConfigureOrder 此需要制定自定配置的顺序时,可以用 @AutoConfigureOrder ,表示绝对顺序(数字越小,优先顺序越高)。
@AutoConfigureBefore@AutoConfigureAfter 控制应用配置类的相对顺序。
具体顺序如下:

  1. 根据类名按照字母表递增排序
  2. 根据 @AutoConfigureOrder value 值(默认:0)递增排序
  3. 根据 @AutoConfigureBefore@AutoConfigureAfter 调整排序
    AutoConfigurationSorter 类是具体实现排序的逻辑

3.Starter编写

在这里插入图片描述在这里插入图片描述

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

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

相关文章

C++之string字符串不同类型间转换

&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3; ✏️作者主页&#xff1a;枫霜剑客 &#x1f4cb; 系列专栏&#xff1a;C实战宝典 &#x1f332;上一篇: VS2019加载解决方案时不能自动打开之前的文档&#xff08…

pytorch 笔记:torch.fft

1 FFT 进行一个维度的快速傅里叶变换 torch.fft.fft(input, nNone, dim- 1, normNone, *, outNone) 1.1 主要参数 input输入&#xff0c;需要傅里叶变换的tensorn 需要变换的tensor的长度&#xff0c;默认是input的长度 如果比input长度大&#xff0c;那么补0如果比input长度…

乐山持点科技:抖音极速版电商入驻指南

“抖音极速版电商”拥有海量活跃用户&#xff0c;着眼下沉市场&#xff0c;为消费者带来高性价比产业带源头好货。针对中小商家设立更宽松的经营要求、提供简单易上手的经营工具&#xff0c;助力商家轻松经营&#xff01;来看入驻指南&#xff1a;一、抖音与抖音极速版电商入驻…

JavaScript基础五、语句

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…

float的表示范围为什么比long大

●很多人会有一个疑问, 一个用来表示小数的 float 为什么表示的范围会比 long 还要大呢 ? ●这次, 咱们就来详细说一说这个事情 从长计议 ●聊到这个话题, 我们就要从计算机存储数字这个位置说起了 ●计算机存储数字的方式其实就是 : 二进制 二进制是计算机中最基本的数字存储…

Java学习笔记 --- jQuery

一、jQuery介绍 jQuery&#xff0c;顾名思义&#xff0c;也就是JavaScript和查询&#xff08;Query&#xff09;&#xff0c;它就是辅助JavaScript开发的js类库。它的核心思想是write less&#xff0c;do more&#xff08;写得更少&#xff0c;做得更多&#xff09;&#xff0c…

2023王道考研数据结构笔记第五章——树

第五章 树 5.1 树的基本概念 树是n&#xff08;n≥0&#xff09;个结点的有限集合&#xff0c;n 0时&#xff0c;称为空树。 空树——结点数为0的树 非空树——①有且仅有一个根节点 ​ ②没有后继的结点称为“叶子结点”&#xff08;或终端结点&#xff09; ​ ③有后继的结…

webStorm svn不显示的问题

看图就行了&#xff0c;怎么下载安装我就不说了&#xff0c;网上一搜全是

<JVM上篇:内存与垃圾回收篇>13 - 垃圾回收器

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录13.1. GC 分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估 GC 的性能指标13.2. 不同的垃圾回收器概述13.…

JavaScript基础一、简介

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…

1.认识网络爬虫

1.认识网络爬虫网络爬虫爬虫的合法性HTTP协议请求与响应(重点)网络爬虫 爬虫的全名叫网络爬虫&#xff0c;简称爬虫。他还有其他的名字&#xff0c;比如网络机器人&#xff0c;网络蜘蛛等等。爬虫就好像一个探测机器&#xff0c;它的基本操作就是模拟人的行为去各个网站溜达&am…

Modbus转profinet网关连接Smart PLC与ABB变频器实现Modbus通信

本案例讲述了modbus转profinet网关&#xff0c;在系统改造中把ABB变频器接入到Smart PLC的Profinet总线上&#xff0c;PLC不用编程实现Profinet转modbus的协议互转&#xff0c;并且SmartPLC485口连接触摸屏采集数据&#xff0c;完成对变频器读写控制 网络拓展图如下图所示&…

达梦数据库运行内存参数配置学习笔记

一、设置运行中的数据库参数 SP_SET_PARA_VALUE(2,MAX_SESSIONS,500) 设置数据库运行参数&#xff0c;参数为 1 表示获取 INI 文件中配置参数的值&#xff0c;为 2 表示获取内存中配置参数的值 二、修改dm.ini数据库运行参数文件&#xff0c;重启数据库 不能动态修改dm.ini参数…

【k8s】安装dashboard以及报错处理

安装步骤&#xff1a; 点击进入dashboard 的 GitHub - kubernetes/dashboard: General-purpose web UI for Kubernetes clustershttps://github.com/kubernetes/dashboard 查看当前k8s版本对应的dashboard版本&#xff0c;点击右边releases 执行对应版本指令安装(我的k8s是v…

近自由电子近似

假设 potential 的变化是非常小的 我们可以找到一条平均线 代表的就是我们的平均值 这样我们用原来的 就可以得到一个 和平均的这条线相比&#xff0c;上下变化不大&#xff0c;这个对我们薛定谔方程求解能带来很大的便利 我们就可以得到一个平均势场 这样的话&#xff0c;…

40-Golang中的文件

Golang中的文件基本介绍文件的打开和关闭读文件操作应用实例写文件操作实例判断文件是否存在基本介绍 文件在程序中是以流的形式存在的 流&#xff1a;数据在数据源(文件)和程序(内存)之间经历的路程 输入流&#xff1a;数据从数据源到程序之间的路径 输出流&#xff1a;数据…

【C++知识点】多态

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…

Java与Winform进行AES加解密数据传输的工具类与对应关系和示例

场景 AndroidJava中使用Aes对称加密的工具类与使用&#xff1a; AndroidJava中使用Aes对称加密的工具类与使用_霸道流氓气质的博客-CSDN博客 上面讲的Java与安卓进行数据传输时使用AES加解密的示例工具类。 如果Java需要与其他第三方平台比如Winform程序进行数据传递时也需…

一文吃透前端低代码的 “神仙生活”

今天来说说前端低代码有多幸福&#xff1f; 低代码是啥&#xff1f;顾名思义少写代码…… 这种情况下带来的幸福有&#xff1a;代码写得少&#xff0c;bug也就越少&#xff08;所谓“少做少错”&#xff09;&#xff0c;因此开发环节的两大支柱性工作“赶需求”和“修bug”就…

智能氮气柜相对于传统氮气柜的优点分析

智能氮气柜是利用氮气置换柜内湿气从而进行除湿&#xff0c;氮气经过流量计&#xff0c;进入智能氮气控制盒&#xff0c;氮气没有氧气和水分&#xff0c;与潮湿气体的比重不同&#xff0c;进入柜内排掉湿气降湿。智能氮气柜在传统氮气柜的基础上加上了智能控制系统&#xff0c;…