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

server/2024/9/23 14:14:00/

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


一、引言

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() 方法。
java">@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 是自动配置的关键。
java">@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 类,该类负责在启动时扫描并导入自动配置类。
java">@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {//............
}

3. AutoConfigurationImportSelector类

  • AutoConfigurationImportSelector 类通过实现 DeferredImportSelector 接口,在Spring容器加载Bean定义时选择性地导入自动配置类。其核心方法是 selectImports,它根据类路径上的条件选择需要导入的自动配置类列表。
java">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应用环境中才生效。
java">@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.ppmy.cn/server/62238.html

相关文章

PostgreSQL安装/卸载(CentOS、Windows)

说明:PostgreSQL与MySQL一样,是一款开源免费的数据库技术,官方口号:The World’s Most Advanced Open Source Relational Database.(世界上最先进的开源关系数据库),本文介绍如何在Windows、Cen…

打造你的智能家居指挥中心:基于STM32的多协议(zigbee、http)网关(附代码示例)

1. 项目概述 随着物联网技术的蓬勃发展,智能家居正逐步融入人们的日常生活。然而,市面上琳琅满目的智能家居设备通常采用不同的通信协议,导致不同品牌设备之间难以实现互联互通。为了解决这一难题,本文设计了一种基于STM32的多协…

VIM模式之间的切换

命令行界面下,常用的文本编辑器是 VI / VIM(VI增强版),VI 是 Linux 最通用的文本编辑器,VIM相较于VI,提供了代码高亮等功能,两者用法完全兼容; 1. 进入 VIM 工作界面 vim 文件名 2. 进入编辑模式 三种方…

基于springboot的鲜花管理系统

系统文档需要联系,白嫖勿扰

第二十一条:为传诸后世而设计接口

这章节主要就是讲解默认(default)方法。 Java8引入了默认方法,目的就是允许向现有的接口中添加方法。但是向现有的接口中添加新方法还是充满风险的。 在存在默认方法的情况下,一个接口的现有实现可能在编译时没有错误或警告&#…

网关设备BL122实现Modbus RTU/TCP转Profinet协议

Modbus与Profinet是两种广泛应用于工业自动化领域的通信协议:Modbus因其简单性和兼容性,在许多工业设备中得到广泛应用;而Profinet提供了高速、高精度的通信能力,适合于复杂控制系统和实时应用,但两者之间的差异导致了…

redis的部署及基本使用

一、redis部署 1、关闭防火墙 关闭防火墙: systemctl stop firewalld.service 状态: firewall-cmd --state 卸载防火墙 yum remove firewalld 2、CentOS7部署redis 1、检查编译运行环境,是否有 GCC 编译器 检查环境(gcc&…

如何PR到别人仓库(指定分支,无废话)

如何PR到别人仓库(指定分支) 记录一下,之前都是直接master分支,现在记录如何pr到别人仓库的其他分支 首先进入别人仓库然后点击fork到自己仓库 步骤(以博主自己一个例子为例) (1)…