Spring Boot 3.3 【二】Spring Boot自动配置机制深度解析

简单动作,深刻联结。在这技术海洋,我备好舟,等你扬帆。启航吧!
🌟点击【关注】,解锁定期的技术惊喜,让灵感与知识的源泉不断涌动。
👍一个【点赞】,如同心照不宣的默契,是我们共同语言的闪亮印记。
📚【收藏】好文,搭建你的专属智慧库,让每次回望都能照亮新知之路。


一、引言

Spring Boot作为Java领域最为流行的快速开发框架之一,其核心特性之一就是其强大的自动配置机制。随着Spring Boot 3.3.1的发布,这一机制得到了进一步的优化和完善,为开发者提供了更加便捷、高效的应用程序搭建和部署体验。本文将深入讲解Spring Boot 3.3.1的自动配置机制,包括其工作原理、特点、优势,并通过实际代码示例和源码解析,展示如何在应用中灵活运用这一机制。此外,我们还将探讨可能遇到的挑战及相应的解决方案。

二、Spring Boot 的前任

在Spring Boot出现之前,使用Spring框架搭建项目时,管理依赖(即JAR包)是一项相对繁琐且容易出错的任务。笔者在当时在搭建项目时,经常遇到以下问题:

1. 依赖管理复杂

  • 手动管理依赖:在Spring Boot之前,项目中的jar包依赖往往需要手动管理,这包括下载、版本控制以及解决依赖冲突等。这一过程既繁琐又容易出错。
  • 版本冲突:不同库之间可能存在版本冲突,手动解决这些冲突需要开发者具备深厚的专业知识和经验。

2. 打包部署不便

  • 打包方式单一:传统的打包方式不够灵活,难以满足现代应用快速迭代和部署的需求。
  • 内置服务器缺乏:许多应用需要外部Tomcat等服务器来运行,这增加了部署的复杂性和对环境的依赖。

3. 运行时配置灵活性不足

  • 配置文件内置:在Spring Boot之前,应用的配置文件通常内置在jar包中,这意味着每次修改配置都需要重新打包和部署,降低了开发和部署的效率。
  • 环境适配性差:不同环境(如开发、测试、生产环境)可能需要不同的配置,内置配置的方式使得环境适配变得复杂和困难。

4. 缺乏统一的构建和部署工具

  • 构建工具多样:在没有Spring Boot之前,Java应用的构建工具多种多样,如Ant、Maven、Gradle等,但缺乏一个统一且广泛接受的标准。
  • 部署流程不统一:不同的项目可能采用不同的部署流程,这增加了维护的复杂性和成本。

三、Spring Boot 的自动配置机制

Spring Boot 的自动配置机制通过提供合理的默认配置、自动扫描和配置、基于条件的自动配置等特点,极大地简化了Spring应用的开发过程,提高了开发效率,并降低了配置错误的风险。同时,它还支持微服务架构、易于集成第三方库、提供丰富的监控和管理功能等优势,使得Spring Boot成为现代Java开发不可或缺的框架之一。

1. 约定优于配置:

  • Spring Boot遵循 “约定优于配置” 的原则,提供了一系列合理的默认配置,开发者只需关注应用的核心业务逻辑,而无需花费大量时间在繁琐的配置上。

2. 自动扫描和配置:

  • Spring Boot启动时会自动扫描项目依赖和类路径中的特定注解(如 @SpringBootApplication ),并根据这些依赖和注解自动配置Spring容器中的Bean。

3. 基于条件的自动配置:

  • 自动配置类通常使用条件注解(如 @ConditionalOnClass@ConditionalOnBean@ConditionalOnProperty等)来确保只有在特定条件满足时才应用配置。这种机制使自动配置更加灵活和智能。

4. 外部化配置:

  • Spring Boot支持将配置信息外部化,通过 application.propertiesapplication.yml 文件来管理配置,这些配置信息可以在运行时被Spring容器读取并绑定到相应的Bean上。

5. Starter POMs:

  • Spring Boot提供了大量的starter POMs,这些starter包含了开发特定类型应用所需的所有依赖。开发者只需在项目中添加相应的starter依赖,Spring Boot就会自动配置好所需的环境。

四、Spring Boot 启动流程分析

1. 启动入口

  • Spring Boot应用的启动通常从main方法开始,该方法中调用 SpringApplication.run() 方法。
@SpringBootApplication  
public class DemoApplication {  public static void main(String[] args) {  SpringApplication.run(DemoApplication.class, args);  }  
}

这里,@SpringBootApplication 是一个组合注解,包含了 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan

2. SpringApplication实例化

  • 在调用 SpringApplication.run() 之前,会首先实例化一个 SpringApplication 对象。这个过程中,Spring Boot会进行一些初始化工作,如推断主类、设置应用类型、加载配置文件等。

3. 加载SpringApplicationRunListeners

  • Spring Boot会加载所有实现了 SpringApplicationRunListener 接口的监听器,这些监听器会在应用启动的不同阶段被触发。

4. 设置应用环境:

  • 准备 Environment 对象,该对象包含了系统的属性和用户配置的属性。
  • 加载 application.propertiesapplication.yml 等配置文件,将配置信息添加到Environment 中。

5. 创建ApplicationContext

  • 根据应用类型(如Web应用或非Web应用)创建合适的 ApplicationContext 实例。
  • 对于Web应用,Spring Boot默认会创建一个嵌入式的Web服务器(如Tomcat)。

5. 准备上下文

  • Environment 设置到 ApplicationContext 中。
  • 应用所有加载的 ApplicationContextInitializer,这些初始化器可以对 ApplicationContext 进行自定义配置。

6. 执行初始化方法

  • 执行所有通过 @Bean 注解声明的初始化方法。

7. 发布事件

  • 在应用启动的不同阶段,Spring Boot会发布不同的事件,监听器可以监听这些事件来执行自定义逻辑。

9. 结束计时器

  • 如果在启动过程中开启了计时器,那么在应用启动完成后会结束计时器,并打印出启动耗时。

五、Spring Boot 核心注解源码解析

为了深入理解自动配置机制的工作原理,我们可以查看Spring Boot的源码。

1. @SpringBootApplication注解

  • @SpringBootApplication 是一个组合注解,它包含了 @EnableAutoConfiguration@SpringBootConfiguration@ComponentScan。其中,@EnableAutoConfiguration 是自动配置的关键。
@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 {//..................
}

2. @EnableAutoConfiguration注解

  • @EnableAutoConfiguration 注解通过 @Import 导入了AutoConfigurationImportSelector 类,该类负责在启动时扫描并导入自动配置类。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {//............
}

3. AutoConfigurationImportSelector类

  • AutoConfigurationImportSelector 类通过实现 DeferredImportSelector 接口,在Spring容器加载Bean定义时选择性地导入自动配置类。其核心方法是 selectImports,它根据类路径上的条件选择需要导入的自动配置类列表。
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {//.........................................@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}//............................
}

4. 自动配置类的条件注解

  • 自动配置类通常使用条件注解(如 @ConditionalOnClass@ConditionalOnBean@ConditionalOnProperty等)来确保只有在特定条件满足时才应用配置。例如,WebMvcAutoConfiguration 类使用 @ConditionalOnWebApplication 注解确保只有在Web应用环境中才生效。
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@ImportRuntimeHints(WebResourcesRuntimeHints.class)
public class WebMvcAutoConfiguration {//......................
}

六、挑战与解决方案

1. 挑战一:默认配置不符合需求

虽然Spring Boot提供了默认配置,但在某些情况下,这些默认配置可能不符合应用的实际需求。

解决方案:

  • 通过 application.propertiesapplication.yml 配置文件覆盖默认配置。
  • 创建自定义配置类,并使用 @Configuration@Bean 注解定义自己的Bean配置。

2. 挑战二:自动配置类冲突

在复杂的项目中,可能会引入多个starter依赖,导致自动配置类之间的冲突。

解决方案:

  • 使用 @SpringBootApplication 注解中的 exclude 属性排除不需要的自动配置类。
  • application.propertiesapplication.yml 中使用 spring.autoconfigure.exclude 属性排除自动配置类。

3. 挑战三:理解自动配置机制复杂

自动配置机制背后涉及多个组件和复杂的逻辑,对于初学者来说可能难以理解。

解决方案:

  • 深入阅读Spring Boot官方文档和源码,理解自动配置的工作原理。
  • 参与社区讨论,关注博主系列博文,反复观看,温故知新。
  • 实践是学习的最佳途径,通过动手编写代码加深对自动配置机制的理解。

结束语

Spring Boot 的自动配置机制极大地简化了Java应用的开发和部署过程,通过默认配置和条件化配置,使得开发者能够更专注于业务逻辑的实现。然而,在实际应用中,我们仍需注意默认配置可能不符合需求、自动配置类冲突以及理解机制复杂等挑战。通过灵活运用配置文件、自定义配置类以及深入学习官方文档和源码,我们可以更好地利用Spring Boot的自动配置机制,提高开发效率和应用质量。

小贴士

在 Spring Boot 2.7 之前,自动配置类通常通过位于 META-INF/spring.factories 文件中的条目进行声明。但从 Spring Boot 2.7 开始,虽然仍支持旧的方式,但推荐使用新的路径 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 来存放自动配置类的导入信息。这一改变旨在提高配置的灵活性和清晰度。

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

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

相关文章

Unity免费领场景多人实时协作地编2人版局域网和LAN联机类似谷歌文档协同合作搭建场景同步资产设置编辑付费版支持10人甚至更多20240709

大家有没有用过谷歌文档、石墨文档、飞书文档等等之类的协同工具呢? Blender也有类似多人联机建模的插件, Unity也有类似的多人合作搭建场景的插件啦。 刚找到一款免费插件,可以支持2人局域网和LAN联机地编。 付费的版本支持组建更大的团队。…

详解如何通过稀疏向量优化信息检索

在信息检索方法的发展历程中,我们见证了从传统的统计关键词匹配到如 BERT 这样的深度学习模型的转变。虽然传统方法提供了坚实的基础,但往往难以精准捕捉文本的语义关系。如 BERT 这样的稠密检索方法通过利用高维向量捕获文本的上下文语义,为…

烟雾识别技术在火灾预防中的应用:思通数科大模型的力量

引言 火灾是导致生命财产损失的重大灾害之一。早期检测和快速响应是预防火灾和减少损失的关键。结合思通数科大模型的烟雾识别技术,为实时检测和精确定位烟雾来源提供了一种高效的解决方案。本文将探讨这一技术如何有效预防火灾并保障人员安全。 烟雾识别技术概述 …

注册自定义总线

1、在/sys/bus下注册一个自定义总线 #include<linux/module.h> #include<linux/init.h> #include<linux/kernel.h> #include<linux/kobject.h> #include<linux/slab.h> #include<linux/sysfs.h> #include<linux/device.h> #include…

bug修复 修复修复修复

好的&#xff0c;这里是更新后的代码&#xff0c;将所有 inRange 函数的第一个变量替换为 ZoomOutimage&#xff1a; // 绿色分岔路 if (divergerColor "green" && nextColor "null") {cv::Mat frameGreen, frameRed;frame2.copyTo(frameGreen)…

如何在 Fedora 中使用 `shred` 擦除驱动器或文件

English Version: https://blog.csdn.net/sch0120/article/details/140390161 如何在 Fedora 中使用 shred 擦除驱动器或文件 安全擦除驱动器对于保护您的敏感数据免受未授权访问至关重要。在这篇博文中&#xff0c;我们将学习如何在 Fedora 中使用 shred 命令安全擦除整个驱…

FATE Flow 源码解析 - 作业提交处理流程

背景介绍 FATE 是隐私计算中最有名的开源项目了&#xff0c;从 star 的数量上来看也可以看出来。截止 2023 年 3 月共收获 4.9k 个 star&#xff0c;但是 FATE 一直被认为代码框架复杂&#xff0c;难以理解&#xff0c;作为一个相关的从业者&#xff0c;后续会持续对 FATE 项目…

React@16.x(56)Redux@4.x(5)- 实现 createStore

目录 1&#xff0c;分析2&#xff0c;实现2.1&#xff0c;基础实现2.2&#xff0c;优化2.2.1&#xff0c;随机字符串2.2.2&#xff0c;action 的判断2.2.2&#xff0c;监听器的优化 2.3&#xff0c;最终形态 1&#xff0c;分析 createStore()&#xff0c;参数1为 reducer&…

0601STM32TIM

TOC 分为四部分&#xff0c;八小节 一部分&#xff1a;主要讲定时器基本定时的功能&#xff0c;也就是定一个事件&#xff0c;让定时器每隔这个时间产生一个中断&#xff0c;来实现每隔一个固定时间来执行一段程序的目的&#xff0c;比如做一个时钟、秒表&#xff0c;或者使用一…

【Linux】1w详解如何实现一个简单的shell

目录 实现思路 1. 交互 获取命令行 2. 子串分割 解析命令行 3. 指令的判断 内建命令 4. 普通命令的执行 补充&#xff1a;vim 文本替换 整体代码 重点思考 1.getenv和putenv是什么意思 2.代码extern char **environ; 3.内建命令是什么 4.lastcode WEXITSTATUS(sta…

Java-final关键字详解

Java-final关键字详解 一、引言 二、什么是 final 关键字&#xff1f; 三、final 变量 final 局部变量 final 实例变量 final 静态变量 四、final 方法 五、final 类 六、final 关键字的实际应用 1. 定义常量 2. 防止方法被重写 3. 创建不可变类 4. 优化性能 七、…

切割01串(牛客小白月赛98)

题意&#xff1a; 给三个整数n&#xff0c;l&#xff0c;r&#xff0c;和一个字符串s&#xff0c;满足l<|c0-c1|<r就可以切成字符串a和字符串b&#xff0c;c0为字符串a左侧出现0的次数&#xff0c;c1为字符串b右侧出现1的次数&#xff0c;求最多切割次数 知识点&#x…

Onnx 1-深度学习-概述1

Onnx 1-深度学习-概述1 一: Onnx 概念1> Onnx 介绍2> Onnx 的作用3> Onnx 应用场景4> Onnx 文件格式1. Protobuf 特点2. onnx.proto3协议3> Onnx 模型基本操作二:Onnx API1> 算子详解2> Onnx 算子介绍三: Onnx 模型1> Onnx 函数功能

昇思学习打卡-8-计算机视觉/FCN图像语义分割

目录 FCN介绍FCN所用的技术训练数据的可视化模型训练模型推理FCN的优点和不足优点不足 FCN介绍 FCN主要用于图像分割领域&#xff0c;是一种端到端的分割方法&#xff0c;是深度学习应用在图像语义分割的开山之作。通过进行像素级的预测直接得出与原图大小相等的label map。因…

【C++基础】初识C++(2)--引用、const、inline、nullptr

目录 一、引用 1.1 引用的概念和定义 1.2 引用的特性 1.3引用的使用 1.4 const引用 1.5 指针和引用的关系 二、inline 三、nullptr 一、引用 1.1 引用的概念和定义 引⽤不是新定义⼀个变量&#xff0c;⽽是给已存在变量取了⼀个别名&#xff0c;编译器不会为引⽤…

微软的人工智能语音生成器在测试中达到与人类同等水平

微软公司开发了一种新的神经编解码语言模型 Vall-E&#xff0c;在自然度、语音鲁棒性和说话者相似性方面都超越了以前的成果。它是同类产品中第一个在两个流行基准测试中达到人类同等水平的产品&#xff0c;而且显然非常逼真&#xff0c;以至于微软不打算向公众开放。 VALL-E …

Node.js 模块系统

Node.js 模块系统 Node.js 的模块系统是其核心特性之一,它允许开发者将代码组织成可重用的模块。这种系统促进了代码的模块化,使得大型应用程序的构建和管理变得更加容易。本文将深入探讨 Node.js 的模块系统,包括其工作原理、如何创建和使用模块,以及模块系统的优势和局限…

【每日一练】python类和对象现实举例详细讲解

""" 本节课程目的&#xff1a; 1.掌握类描述现实世界实物思想 2.掌握类和对象的关系 3.理解什么事面向对象 """ #比如设计一个闹钟&#xff0c;在这里就新建一个类 class Clock:idNone #闹钟的序列号&#xff0c;也就是类的属性priceNone #闹…

Git最常用操作速查表

Git常用操作 文章目录 Git常用操作1. 克隆/拉取2. 分支操作1. 查看分支2. 创建分支3. 切换到分支4. 删除分支5. 删除远程分支6. 推送分支到远程 3. 暂存库操作4. Git团队规范1. 原则2. 分支设计3. commit备注一般规范 1. 克隆/拉取 git clone xxx 从远程仓库克隆 git rebase…

【开源之美】:WinMerge Files

一、引言 强大的windows端文件比较工具&#xff0c;跟Beyond Compare相比&#xff0c;更为强大。但是这里我们推荐他的原因&#xff0c;不仅是因为作为一个使用的工具&#xff0c;主要是因为他开源&#xff0c;可以通过调试优秀的源代码&#xff0c;进一步的提升C项目设计和编…