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

news2024/12/26 11:43:10

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.coloradmin.cn/o/1942258.html

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

相关文章

C++ | Leetcode C++题解之第264题丑数II

题目&#xff1a; 题解&#xff1a; class Solution { public:int nthUglyNumber(int n) {vector<int> dp(n 1);dp[1] 1;int p2 1, p3 1, p5 1;for (int i 2; i < n; i) {int num2 dp[p2] * 2, num3 dp[p3] * 3, num5 dp[p5] * 5;dp[i] min(min(num2, num3…

CTF-Web习题:2019强网杯 UPLOAD

题目链接&#xff1a;2019强网杯 UPLOAD 解题思路 打开靶场如下图所示&#xff0c;是一个注册和登录界面 那就注册登录一下&#xff0c;发现是一个提交头像的页面&#xff1a; 试了一下只有能正确显示的png图片才能提交成功&#xff0c;同时F12拿到cookie&#xff0c;base6…

自己开发软件实现网站抓取m3u8链接

几天前一个同学说想下载一个网站的视频找不到连接&#xff0c;问我有没有什么办法,网站抓取m3u8链接 网页抓取m3u8链接。当时一听觉得应该简单&#xff0c;于是说我抽空看看。然后就分析目标网页&#xff0c;试图从网页源码里找出连接&#xff0c;有的源代码直接有,但是有的没有…

与Bug较量:Codigger之软件项目体检Software Project HealthCheck来帮忙

在软件工程师的世界里&#xff0c;与 Java 小程序中的 Bug 作战是一场永不停歇的战役。每一个隐藏在代码深处的 Bug 都像是一个狡猾的敌人&#xff0c;时刻准备着给我们的项目带来麻烦。 最近&#xff0c;我就陷入了这样一场与 Java 小程序 Bug 的激烈较量中。这个小程序原本应…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十九章 Linux MISC驱动

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

爬虫实战:解决代理IP频繁中断的实操建议

当代理IP在爬虫中频繁掉线时&#xff0c;我们先要了解出现问题的可能原因&#xff0c;这不仅限于技术性因素&#xff0c;还涉及操作策略和环境因素。只有在找到具体原因后&#xff0c;才能针对问题类型从源头解决IP掉线问题。 一、问题原因&#xff1a; 1. 代理IP质量问题导致…

数据结构(Java):七大排序算法【详解】

目录 1、排序的概念 1.1 排序 1.2 排序的稳定性 1.3 内部排序&外部排序 1.4 各排序算法总结对比 2、 插入排序 2.1 &#x1f338;直接插入排序 2.2 &#x1f338;希尔排序 3、 选择排序 3.1 &#x1f338;直接选择排序 3.2 直接选择排序优化 3.3 &#x1f338;…

清华大学联合斯坦福大学提出混合注意力机制MoA,大模型解码速率提高6倍

随着大语言模型的规模不断扩大&#xff0c;如何在保持模型性能的同时提高其效率&#xff0c;成为了当前研究的热点问题。最近&#xff0c;清华大学联合斯坦福大学提出一种名为"注意力混合"(Mixture of Attention, MoA)的新方法&#xff0c;用于自动压缩大语言模型。 …

ES中的数据类型学习之ALIAS

Alias field type | Elasticsearch Guide [7.17] | Elastic 这里只针对data type的alias&#xff0c;暂时不说 index的alias。直接实战开始 PUT trips { "mappings": { "properties": { "distance": { "type": &…

开源安全态势感知平台Security Onion

简介 Security Onion是一款由安全防御人员为安全防御人员构建的免费开放平台。它包括网络可见性、主机可见性、入侵检测蜜罐、日志管理和案例管理等功能。详细信息可以查看官网Security Onion Solutions 在网络可见性方面&#xff0c;Security Onion提供了基于签名的检测&…

【系统架构设计 每日一问】二 MySql主从复制延迟可能是什么原因,怎么解决

主从复制的架构设计如下图所示&#xff1a; 同步原理 具体到数据库之间是通过binlog和复制线程操作的&#xff1a; Master的更新事件(update、insert、delete)会按照顺序写入bin-log中。当Slave连接到Master的后,Master机器会为Slave开启&#xff0c;binlog dump线程,该线程…

go关于string与[]byte再学深一点

目标&#xff1a;充分理解string与[]bytes零拷贝转换的实现 先回顾下string与[]byte的基本知识 1. string与[]byte的数据结构 reflect包中关于字符串的数据结构 // StringHeader is the runtime representation of a string.type StringHeader struct {Data uintptrLen int} …

浅谈断言之XML断言

浅谈断言之XML断言 XML断言是JMeter的一个组件&#xff0c;用于验证请求的响应数据是否符合XML结构。这对于测试返回XML格式数据的Web服务特别有用。 如何添加XML断言&#xff1f; 要在JMeter测试计划中添加XML断言&#xff0c;遵循以下步骤&#xff1a; 打开测试计划&…

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】 目录 JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现CPO-Transformer-LSTM多变量回归预测…

基于STM32F103的FreeRTOS系列(二)·多任务系统

基于STM32F103的FreeRTOS系列&#xff08;一&#xff09;单片机设计模式介绍裸机程序的设计模式-CSDN博客 目录 1. 多任务模式 2. 互斥操作 3. 同步操作 1. 多任务模式 对于裸机程序&#xff0c;无论使用哪种模式进行精心的设计&#xff0c;在最差的情况下都无法解决这个…

12. Hibernate 模板设计模式

1. 前言 本节课和大家一起使用模板设计模式重构 Hibernate 操作流程&#xff0c;通过本节课程内容&#xff0c;你将了解到&#xff1a; 如何运用模板设计模式重构 Hibernate 操作流程&#xff1b;持久化对象与序列化接口&#xff1b; 2. 模板设计模式 学习 Hibernate 的过程…

服务器上使用Docker部署sonarQube,并集成到Jenkins实现自动化。

目标是要在目标服务器上使用docker工具部署好sonar环境&#xff0c;然后再集成到Jenkins中实现自动化的代码审查工作。 Docker 首先Dokcer的源大部分现在都用不了&#xff0c;于是我上网查询&#xff0c;终于找到了一个可用的镜像。 编辑/etc/docker/daemon.json文件&#x…

71.PLC Settings for OPCSERVER(KEPWare)- SAP ME实施

目录 0.目的 1.三菱PLCMitsubishi Ethernet 1.1 型号FX-3U的配置 选择Operational settings 按下图设置通讯参数 选择Open settings 按下图设置通讯端口 选择Router ralay parameter 按下图设置网关 1.2型号Q Series 按下图设置IP、网关 按下图设置端口…

WebGoC题解(13) 狐猬编程:GoC L4 结业测试 第4题 找木柴

题目描述 小明今天找了n跟木柴&#xff0c;但是木柴太多了&#xff0c;小明只能拿走m根木柴&#xff0c;小明希望拿走的木柴都是剩下的木柴中最长的&#xff0c;小明还画出以下图形 例如 输入 5 3 10 20 30 40 50 小明要拿走30 40 50 这3根木柴 从大到小画出以下图形 矩形的宽…

AWS监控工具,监控性能指标

执行AWS监视是为了跟踪在AWS环境中主动运行的应用程序工作负载和资源&#xff0c;AWS监视器跟踪各种AWS云指标&#xff0c;以帮助提高在其上运行的应用程序的整体性能。 借助阈值突破警报系统&#xff0c;AWS应用程序监控在识别性能瓶颈来源方面起着至关重要的作用&#xff0c…