【详细的springboot自动装载原理】

1.默认提供的核心配置模块

springboot提供了 spring-boot-autoconfigure模块,该模块为springboot自动配置的核心模块,它初始化好了很多我们平时需要的配置类,那么有了这些配置类就能生效了吗?得需要一个东西在启动的时候去把它加载进容器里。

2.启动配置类注解 @SpringBootApplication

  • @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 {

该注解是个复合注解,包含了

  • @SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

这个注解触发了自动配置的过程。它实际上导入了 AutoConfigurationImportSelector 类,这个类负责决定哪些自动配置类应该被添加到应用上下文中。

这是一个复合注解,它包含了 @Configuration 注解,意味着当前类是一个配置类,可以包含一个或多个 @Bean 方法来定义组件。

  • @EnableAutoConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

这个注解触发了自动配置的过程。它实际上导入了 AutoConfigurationImportSelector 类,这个类负责决定哪些自动配置类应该被添加到应用上下文中。

  • AutoConfigurationImportSelector
    AutoConfigurationImportSelector 类的 selectImports() 方法会返回一个字符串数组,即 factoryClassNames,这些类名代表了候选的自动配置类。这些类通常是 AutoConfigureXXX 的形式,它们会根据不同的条件(如类路径上的类、系统属性、环境变量等)来决定是否应该被激活。

3.条件注解,选择性加载

再来看这些配置类的具体实现,随便找一个
在这里插入图片描述

这些类上了使用条件注解,@Conditional**,这些条件控制了这些配置类什么时候生效,也就是说,当我们需要使用新的功能时必须引入这些依赖,导入对应的start pom, 导入之后这些配置类才会生效。

4.配置类的维护

在该依赖模块下的 META-INF/spring.factories 文件里提供了所有需要自动装配的配置类,

所有满足条件的自动配置类会通过 @Bean 方法创建并注册新的 Bean 到 Spring 容器中。

5.组件扫描

Spring Boot 会扫描标注了 @SpringBootApplication 的主类以及其子包,寻找带有 @Component、@Service、@Repository 和 @Controller 等注解的类,并将它们作为 Bean 注册到容器中。

6.依赖注入

所有注册的 Bean 将根据其定义的依赖关系进行自动装配,例如使用 @Autowired 注解。

7.源码细节

1.初始化自动配置类

 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");MultiValueMap<String, String> result = new LinkedMultiValueMap();while(urls.hasMoreElements()) {URL url = (URL)urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Map.Entry<?, ?> entry = (Map.Entry)var6.next();List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));result.addAll((String)entry.getKey(), factoryClassNames);}}cache.put(classLoader, result);return result;} catch (IOException var9) {IOException ex = var9;throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", ex);}}}

2.容器启动-> 进入AutoConfigurationImportSelector->

public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {//加载所有的自动配置类AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = this.getAttributes(annotationMetadata);//获取候选配置 获取满足条件的自动配置类List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);configurations = this.removeDuplicates(configurations);//获取在springboot启动类上的排除的类 如@SpringBootApplication(scanBasePackages =             		   //{"com.crpcg.ohps.weixin"}, exclude = {RabbitAutoConfiguration.class})Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);//移除需要排除的配置类configurations.removeAll(exclusions);configurations = this.filter(configurations, autoConfigurationMetadata);//继续往下看 下面有详细的源码this.fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}}

->进入到fireAutoConfigurationImportEvents方法

参数

configurations 自动配置类

exclusions 需要排除的配置类

源码基础补充

AutoConfigurationImportListener 会遍历这个列表,对于每一个自动配置类,它会检查该类是否满足激活条件(如 @ConditionalOnClass、@ConditionalOnBean、@ConditionalOnProperty 等)。如果条件满足,它会将该类注册为一个 Bean 定义,这样 Spring 容器就能在后续的初始化过程中创建和管理这些 Bean。

private void fireAutoConfigurationImportEvents(List<String> configurations,Set<String> exclusions) {List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();if (!listeners.isEmpty()) {AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,configurations, exclusions);for (AutoConfigurationImportListener listener : listeners) {//继续往里面看再下面invokeAwareMethods(listener);//处理自动配置的导入和激活。 listener.onAutoConfigurationImportEvent(event);}}
}

listeners变量实例化之后的值,是一个条件判断listener
在这里插入图片描述

再往里看,执行的

private void invokeAwareMethods(Object instance) {if (instance instanceof Aware) {if (instance instanceof BeanClassLoaderAware) {((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);}if (instance instanceof BeanFactoryAware) {((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);}if (instance instanceof EnvironmentAware) {((EnvironmentAware) instance).setEnvironment(this.environment);}if (instance instanceof ResourceLoaderAware) {((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);}}
}

在这里插入图片描述

目前处于对象创建阶段,所以进入到了BeanFactoryAware

执行完返回继续执行

listener.onAutoConfigurationImportEvent(event);
//在注册自动配置类的过程中,onAutoConfigurationImportEvent 方法会评估每个自动配置类上的条件注解,如 //@ConditionalOnClass、@ConditionalOnBean、@ConditionalOnMissingBean 等,以确定它们是否应该被实际激活。
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {if (this.beanFactory != null) {//这个报告记录了哪些条件被评估以及它们的结果。这对于调试和理解为什么某些自动配置类被激活或未被激活是非常有用的。ConditionEvaluationReport report = ConditionEvaluationReport.get(this.beanFactory);report.recordEvaluationCandidates(event.getCandidateConfigurations());report.recordExclusions(event.getExclusions());}}

Spring Boot 会启动一个监听器,监听应用上下文的启动事件,一旦所有的 Bean 加载完毕,监听器会触发 ApplicationReadyEvent 事件,表明应用已经准备好接受请求。这样就完成了整个配置类的加载

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

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

相关文章

uniapp 小程序 嵌套 webview 返回需要点击两次

uniapp 小程序 嵌套 webview 返回需要点击两次 先 上图 小程序也监听不到 返回事件在网上找了一圈 都没有理想的答案&#xff0c;猜测 是因为嵌入的页面中有问题果然 小程序中嵌入的代码 <view><web-view :src"urlSrc" ></web-view></view>…

jdk1.8 List集合Stream流式处理

jdk1.8 List集合Stream流式处理 一、介绍(为什么需要流Stream&#xff0c;能解决什么问题&#xff1f;)1.1 什么是 Stream&#xff1f;1.2 常见的创建Stream方法1.3 常见的中间操作1.4 常见的终端操作 二、创建流Stream2.1 Collection的.stream()方法2.2 数组创建流2.3 静态工厂…

理解进程status的二进制位表示及进程等待(是什么,为什么,怎么办)

信号编号&#xff1a;低7位 状态编号&#xff1a;次低8位 1.子进程退出后会变为僵尸进程&#xff0c;将退出结果写入自身的task_struct结构体中 2.wait/waitpid是一个系统调用->OS可以读取子进程的task_struct 1.为什么要进行进程等待&#xff1f; 1.将子进程&#xff…

C语言 | Leetcode C语言题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; #define ADDITION -1 #define SUBTRACTION -2 #define MULTIPLICATION -3int* diffWaysToCompute(char * expression, int* returnSize) {int len strlen(expression);int *ops (int *)malloc(sizeof(int) * len);int opsSize 0;for (in…

单周期CPU(三)译码模块(minisys)(verilog)(vivado)

timescale 1ns / 1ps //module Idecode32 (input reset,input clock,output [31:0] read_data_1, // 输出的第一操作数output [31:0] read_data_2, // 输出的第二操作数input [31:0] Instruction, // 取指单元来的指令input [31:0] …

前台文本直接取数据库值doFieldSQL插入SQL

实现功能&#xff1a;根据选择的车间主任带出角色。 实现步骤&#xff1a;OA的“字段联动”功能下拉选项带不出表“hrmrolemembers”&#xff0c;所以采用此方法。 doFieldSQL("select roleid from HrmResource as a inner join hrmrolemembers as b on a.id b.resource…

快速排序【示例】

冒泡排序可以说是我们学习的第一个真正的排序算法&#xff0c;并且解决了桶排序浪费 空间的问题&#xff0c;但在算法的执行效率上却牺牲了很多&#xff0c;它的时间复杂度达到了 O(N^2)。假如我 们的计算机每秒钟可以运行 10 亿次&#xff0c;那么对 1 亿个数进行排序&#xf…

【京存】助力《抓娃娃》后期制作!

沈腾马丽合体爆改偷感夫妇&#xff0c;暑期开大贴脸开笑!!西虹市IP爆笑回归!! 困苦的爹&#xff0c;辛劳的妈&#xff0c;破烂的院子&#xff0c;破碎的他。西虹市做大做强的路上怎么把老马家落下了?!!! “汤里没油&#xff0c;兜里没子”的马成钢(沈腾 饰)和春兰(马丽 饰)&…

收银系统源码-线上商城diy装修

线下线上一体化收银系统越来越受门店重视&#xff0c;尤其是连锁多门店&#xff0c;想通过线下线上相互带动&#xff0c;相互引流&#xff0c;提升门店营业额。商城商城如何装修呢&#xff1f; 1.收银系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网…

使用Django Rest Framework构建API

Django Rest Framework (DRF) 是一个强大且灵活的工具集&#xff0c;用以构建Web API。它基于Django&#xff0c;一个非常流行的Python Web框架。在本文中&#xff0c;我们将深入探讨如何使用DRF来构建一个高效、结构化的API。 目录 使用Django Rest Framework构建API 一、环…

【SQLServer】如何设计日增几十万数据量的业务分库分表方案

随着公司的业务发展不断的壮大&#xff0c;像一些核心的业务&#xff08;如订单&#xff09;数据量会越来越大&#xff0c;此时就需要考虑分库分表方案来应对业务的发展。今天就来聊聊分库分表的一些设计方案。 1、冷热数据分离方案 在我们业务中有些数据只是最近一段时间使用…

世平基于 NXP UWB Digital-Key Kit 应用方案

大联大世平集团针对汽车数字钥匙&#xff0c;推出了基于 NXP UWB Digital-Key Kit 解决方案。此方案基于超宽带&#xff08;UWB&#xff09;技术&#xff0c;利用 UWB 技术的高精度定位和距离测量能力&#xff0c;实现了安全、便捷的数字钥匙功能。该套件主要器件有 NXP 的 UWB…

14、如何⽤DDD设计微服务代码模型

在完成领域模型设计后&#xff0c;接下来我们就可以开始微服务的设计和 落地了。在微服务落地前&#xff0c;⾸先要确定微服务的代码结构&#xff0c;也就是我 下⾯要讲的微服务代码模型。 只有建⽴了标准的微服务代码模型和代码规范后&#xff0c;我们才可以将 领域对象映射到…

AgentMD:通过大规模临床工具学习提升语言代理的风险预测能力

人工智能咨询培训老师叶梓 转载标明出处 临床计算器在医疗保健中扮演着至关重要的角色&#xff0c;它们通过提供准确的基于证据的预测来辅助临床医生进行诊断和预后评估。然而&#xff0c;由于可用性挑战、传播不畅和功能受限&#xff0c;这些工具的广泛应用常常受限。为了克服…

Django视图与URLs路由详解

在Django Web框架中&#xff0c;视图&#xff08;Views&#xff09;和URLs路由&#xff08;URL routing&#xff09;是Web应用开发的核心概念。它们共同负责将用户的请求映射到相应的Python函数&#xff0c;并返回适当的响应。本篇博客将深入探讨Django的视图和URLs路由系统&am…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十八章 Platform 设备驱动

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

java的DOS命令

目录 1.DOS命令了解 DOS介绍 常用的dos命令1 DOS的基本原理 相对路径与绝对路径 常用的dos命令2 2.本章作业 1.编写hello&#xff0c;world程序 2.输出个人基本信息 3.jdk&#xff0c;jre&#xff0c;jvm关系 4.环境变量path配置及作用 5.java编写步骤 6.java编写7…

昇思25天学习打卡营第4天 | 网络构建

在学习和实践MindSpore神经网络模型构建的过程中&#xff0c;我深刻理解了MindSpore中如何通过nn.Cell类来构建和管理复杂的神经网络模型。通过这次的实践&#xff0c;我对神经网络的基本构建和应用有了更加全面的认识&#xff0c;以下是我学习过程中所总结的几点心得&#xff…

科普文:云计算服务类型IaaS, PaaS, SaaS, BaaS, Faas说明

概叙 基本概念 IaaS, PaaS, SaaS, BaaS, 和 FaaS 是云计算服务的不同类型&#xff0c;‌它们各自提供了不同的服务层次和功能。‌ IaaS (Infrastructure as a Service基础设施即服务) 提供基础设施服务&#xff0c;‌包括服务器、‌存储、‌网络等硬件资源。‌用户可以在这些…

Linux嵌入式学习——数据结构——概念和Seqlist

数据结构 相互之间存在一种或多种特定关系的数据元素的集合。 逻辑结构 集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等。 线性&#xff0c;数据和数据之间是一对一的关系。数组就是线性表的一种。 树&#xff0c; 一对多 图&#xff0c;多对多 …