Spring Boot 的自动配置是其 "约定大于配置" 理念的核心实现,它能自动配置 Spring 应用所需的各种组件,大幅减少手动配置。下面从核心注解、加载流程、条件过滤等方面详细讲解其原理,并结合关键源码说明。

一、自动配置的入口:@SpringBootApplication 注解

Spring Boot 应用的启动类通常标注@SpringBootApplication,这个注解是自动配置的起点,它是一个 "复合注解",包含三个核心注解:

  • @SpringBootConfiguration:本质是@Configuration,标识当前类是配置类
  • @ComponentScan:扫描当前包及子包的组件(如@Component@Service等)
  • @EnableAutoConfiguration启用自动配置的核心注解
源码:@SpringBootApplication

java运行

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 等同于@Configuration
@ComponentScan(excludeFilters = { // 扫描组件@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
@EnableAutoConfiguration // 关键:启用自动配置
public @interface SpringBootApplication {// 排除指定的自动配置类Class<?>[] exclude() default {};String[] excludeName() default {};// ... 其他属性
}

二、@EnableAutoConfiguration:自动配置的开关

@EnableAutoConfiguration的核心作用是触发 Spring 容器自动导入符合条件的配置类,其实现依赖@Import注解导入AutoConfigurationImportSelector类。

源码:@EnableAutoConfiguration

java运行

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage // 自动注册当前包为基础包(用于扫描@Entity等)
@Import(AutoConfigurationImportSelector.class) // 关键:导入选择器
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";// 排除不需要的自动配置类Class<?>[] exclude() default {};String[] excludeName() default {};
}

三、AutoConfigurationImportSelector:自动配置类的 "导入器"

AutoConfigurationImportSelector是自动配置的核心类,它通过selectImports方法筛选并导入符合条件的自动配置类,流程如下:

1. 核心方法:selectImports

该方法返回需要导入的自动配置类全类名数组,核心逻辑是获取候选配置类并过滤。

java运行

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, etc. {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) { // 检查是否启用自动配置(默认启用)return NO_IMPORTS;}// 1. 加载自动配置的元数据(条件注解等信息)AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);// 2. 获取所有候选的自动配置类AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}// 关键:获取自动配置入口(筛选候选类)protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {// ... 检查是否启用(省略)// 1. 获取所有候选的自动配置类(从spring.factories加载)List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 2. 去重configurations = removeDuplicates(configurations);// 3. 排除用户指定的自动配置类(通过exclude属性)Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);// 4. 基于条件注解过滤(核心:只保留符合条件的配置类)configurations = filter(configurations, autoConfigurationMetadata);// ... 其他处理(发布事件等)return new AutoConfigurationEntry(configurations, exclusions);}
}
2. 加载候选配置类:getCandidateConfigurations

getCandidateConfigurations通过SpringFactoriesLoader从类路径下的META-INF/spring.factories文件中加载自动配置类。

java运行

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// 从spring.factories中加载key为EnableAutoConfiguration的配置类List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. " +"If you are using a custom packaging, make sure that file is correct.");return configurations;
}// 指定加载的类型为EnableAutoConfiguration
protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}

四、SpringFactoriesLoader:SPI 机制的实现

SpringFactoriesLoader是 Spring 的一种 SPI(Service Provider Interface)实现,用于从类路径的META-INF/spring.factories文件中加载指定类型的实现类

源码:SpringFactoriesLoader.loadFactoryNames

java运行

public final class SpringFactoriesLoader {public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {String factoryTypeName = factoryType.getName();// 加载所有spring.factories文件,返回key为接口名、value为实现类列表的Mapreturn loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {// 查找类路径下所有META-INF/spring.factories文件Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);// 解析文件为Properties(key=接口全类名,value=实现类全类名逗号分隔)Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}}
}
spring.factories 文件示例

Spring Boot 的spring-boot-autoconfigure包中包含META-INF/spring.factories,其中定义了大量自动配置类:

properties

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
# ... 其他数百个自动配置类

五、条件注解:过滤生效的自动配置类

spring.factories加载的候选配置类并非全部生效,Spring Boot 通过条件注解@Conditional系列)筛选符合当前环境的配置类。

常见条件注解:

  • @ConditionalOnClass:类路径存在指定类时生效
  • @ConditionalOnMissingClass:类路径不存在指定类时生效
  • @ConditionalOnBean:容器中存在指定 Bean 时生效
  • @ConditionalOnMissingBean:容器中不存在指定 Bean 时生效
  • @ConditionalOnProperty:配置文件中存在指定属性时生效
  • @ConditionalOnWebApplication:当前是 Web 应用时生效
示例:DispatcherServletAutoConfiguration

Spring MVC 的 DispatcherServlet 自动配置类,通过条件注解控制生效时机:

java运行

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET) // 仅在Servlet Web应用中生效
@ConditionalOnClass(DispatcherServlet.class) // 类路径存在DispatcherServlet时生效
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) // 在指定配置类之后加载
public class DispatcherServletAutoConfiguration {// 定义DispatcherServlet的Bean@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)@ConditionalOnMissingBean(DispatcherServlet.class) // 容器中没有DispatcherServlet时才创建public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {DispatcherServlet dispatcherServlet = new DispatcherServlet();dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());// ... 配置其他属性return dispatcherServlet;}
}

六、自动配置的完整流程总结

  1. 启动触发@SpringBootApplication包含@EnableAutoConfiguration,开启自动配置。
  2. 导入选择器@EnableAutoConfiguration通过@Import导入AutoConfigurationImportSelector
  3. 加载候选类AutoConfigurationImportSelector通过SpringFactoriesLoaderMETA-INF/spring.factories加载所有EnableAutoConfiguration对应的自动配置类。
  4. 过滤配置类
    • 排除用户指定的类(exclude属性)。
    • 通过条件注解(如@ConditionalOnClass)筛选符合当前环境的配置类。
  5. 注册 Bean:生效的自动配置类(@Configuration)通过@Bean向容器注册组件,完成自动配置。

通过这套机制,Spring Boot 实现了 "引入 starter 依赖即可自动配置组件" 的便捷性,开发者无需手动编写大量 XML 或 Java 配置。

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

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

相关文章

谷歌云平台(Google Cloud Platform, GCP)介绍(全球领先的云计算服务平台,为企业和开发者提供包括计算、存储、数据分析、人工智能、机器学习、网络和安全等在内的全面云服务)

文章目录**1. GCP的核心优势****1.1 全球领先的基础设施****1.2 强大的数据分析和人工智能能力****1.3 卓越的安全性和合规性****1.4 灵活的定价模式****2. GCP的主要服务****2.1 计算服务****2.2 存储和数据库****2.3 网络服务****2.4 人工智能与大数据****2.5 安全与管理工具…

RISC-V异常机制和异常定位

不少人在调试RISC-V core时&#xff0c;面对异常的出现不知所措&#xff0c;不知道如何定位代码问题。这里将从RISC-V异常机制以及几个异常实例学习下。 1 异常机制 1.1 什么是异常 异常是软件程序员不得不要深入了解的&#xff0c;首先在学习异常机制前&#xff0c;对异常要…

c++中导出函数调用约定为__stdcall类型函数并指定导出函数名称

开发环境在Visual studio 2022版本下&#xff0c;为防止编译器重命名函数名称&#xff08;会加上8等等乱七八糟的东西&#xff09;&#xff0c;我们对函数名称进行指定&#xff1a;一、新建.def文件&#xff0c;名称须与dll名称相同&#xff0c;并放在与cpp文件相同文件夹下&am…

Vision Transformer (ViT) :Transformer在computer vision领域的应用(二)

METHOD,论文主要部分 In model design we follow the original Transformer (Vaswani et al., 2017) as closely as possible. An advantage of this intentionally simple setup is that scalable NLP Transformer architectures – and their efficient implementations –…

AI 论文周报丨红队测试语言模型/多视角 3D 点追踪方法/蛋白质表示学习框架/密码学漏洞检测新框架……

近年来&#xff0c;已有若干方法尝试从单目视频实现 3D 点跟踪&#xff0c;然而由于在遮挡和复杂运动等挑战性场景中难以准确估计 3D 信息&#xff0c;这些方法的性能仍难以满足实际应用对高精度与鲁棒性的要求。 基于此&#xff0c;苏黎世联邦理工学院、卡内基梅隆大学联合提出…

STM32 通过USB的Mass Storage Class读写挂载的SD卡出现卡死问题

问题描述&#xff1a;使用stm32cubemx生成的sdio和usb Mass Storage Class的代码后&#xff0c;在USB_DEVICE\App\usbd_storage_if.c文件里面的接口调用以下函数出现卡死问题&#xff1a; SD_Driver.disk_initialize(0); SD_Driver.disk_read(lun, buf, blk_addr, blk_len) SD_…

Go语言中 error 接口与自定义错误类型的深入解析

在 Go 语言开发中&#xff0c;我们经常需要处理各种错误情况。Go 语言通过 error 接口提供了一套简洁而强大的错误处理机制。然而&#xff0c;当涉及到自定义错误类型时&#xff0c;许多开发者会遇到一些令人困惑的问题。本文将通过一个实际案例来深入探讨这个问题。 问题背景 …

字幕编辑工具推荐,Subtitle Edit v4.0.13发布:增强语音识别+优化翻译功能

大家好呀&#xff0c;不知道大家有没有做自媒体相关工作的呢&#xff0c;你们是不是也觉得剪辑视频时最头疼的往往不是画面而是字幕&#xff0c;时间轴对不上、格式不兼容、需要手动翻译&#xff0c;这些琐碎工作消耗的精力甚至超过剪辑本身。 当你试遍各种在线工具却发现要么…

【Java后端】Spring Boot 集成雪花算法唯一 ID

Spring Boot 实现基于雪花算法的分布式唯一 ID 生成器在分布式系统中&#xff0c;我们经常需要生成 全局唯一 ID&#xff0c;比如用户 ID、订单号、消息 ID 等。常见的方式有&#xff1a;数据库自增主键、UUID、Redis/Zookeeper 分布式 ID 服务、百度 UidGenerator、美团 Leaf …

C语言初尝试——洛谷

一、C数组&#xff1a;C 语言支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。声明数组在 C 中要声明一个数组&#xff0c;需要指定元素的类型和元素的数量&#xf…

C++八大排序

C排序算法一、概览二、代码实现1.冒泡排序2.插入排序3.希尔排序4.堆排序5.选择排序6.快速排序7.归并排序三、排序时间、空间复杂度总结排序&#xff0c;是C各大算法当中非常常见的一个步骤&#xff08;过程&#xff09;&#xff0c;通常我们使用便捷的algorithmalgorithmalgori…

每天五分钟深度学习:深层神经网络的优势

本文重点 在人工智能领域,深层神经网络(DNN)的崛起标志着技术范式的根本性转变。相较于传统浅层神经网络(如单层感知机、线性回归模型),深层网络通过引入多层隐藏层,实现了对复杂数据模式的深度解析与高效建模。 深层神经网络 神经网络中输入层表示神经网络的第0层,…

相机几何 空间点到像素平面转换

一个空间中点到像素平面转换&#xff0c;需要经过1. 空间坐标系转换到相机坐标系2. 相机坐标系下3D点到相机平面转换3. 相机平面到像素平面转换相机三维空间到像素平面转换1. 3D点到相机平面转换2. 相机平面到像素平面转换涉及到单位的转换&#xff0c;和像素原点到相机平面原点…

webpack5 vue3同一仓库,不同命令切换项目

技术方案&#xff1a;手动输入不同的命令&#xff0c;启动不同项目。实现这种能力本篇文章是通过不同路由划分&#xff0c;进而实现不同项目的划分。所以简单来说就是通过输入不同命令行在webpack中找到不同项目的路由&#xff0c;进而打不同项目的包&#xff0c;实现项目隔离。…

PowerBI实战-制作带有同比及趋势线的双柱状图

一、引言 今天的PowerBI报表的制作相对有一点复杂&#xff0c;我们直接根据最终展示图来讲解&#xff1a; 可以看到&#xff0c;我们今天要制作的图像需要包括以下几点&#xff1a;时间维度的趋势、两种不同维度的数据对比、不同数据标签的展示、不同年份间环比的标签展示以及…

物联网智能网关配置教程:实现注塑机数据经基恩士PLC上传至云平台

一、项目背景随着制造业向智能化、信息化方向快速发展&#xff0c;注塑车间作为塑料制品制造的核心环节&#xff0c;面临着设备协议多样、数据孤岛严重、系统集成困难等问题。某大型注塑企业计划对其老旧车间进行数字化改造&#xff0c;实现设备数据采集、远程监控与MES系统对接…

【实战】预警算法--噪声添加机制

1. 背景 在多变量自联想预测或异常检测场景中&#xff0c;我们常使用带噪自编码器&#xff08;Denoising AutoEncoder&#xff0c;DAE&#xff09;来训练模型&#xff0c;使模型能够从带噪输入中重构原始数据。噪声的添加方式对训练效果、稳定性以及模型用途有显著影响。 2. 两…

ChromaDB探索

关于 ChromaDB、向量与 RAG 系统的核心知识问答总结 ​​Q1: ChromaDB 是什么&#xff1f;它在数据库领域中扮演什么角色&#xff1f;​​​​A:​​ ChromaDB 是一款开源的​​向量数据库​​。它的核心角色是专门为 AI 应用&#xff08;如语义搜索、推荐系统、RAG&#xff09…

C# 基于halcon的视觉工作流-章33-矩状测量

C# 基于halcon的视觉工作流-章33-矩状测量 本章目标&#xff1a; 一、gen_measure_rectangle2准备提取垂直于矩形的直边&#xff1b; 二、measure_pos 提取垂直于矩形或环形弧的直线边缘&#xff1b; 三、measure_pairs提取垂直于矩形或环形弧长轴的直边对&#xff1b; 四、匹配…

Day05_苍穹外卖——Redis店铺营业状态设置

目录1.1 Redis简介1.2 Redis下载与安装1.2.1 Redis下载1.2.2 Redis安装1.3 Redis服务启动与停止1.3.1 服务启动命令1.3.2 客户端连接命令1.3.3 修改Redis配置文件1.3.4 Redis客户端图形工具2. Redis数据类型2.1 五种常用数据类型介绍2.2 各种数据类型特点3. Redis常用命令3.1 字…