SpringBoot学习路径二--Spring Boot自动配置原理深度解析

        SpringBoot最核心的功能就是自动装配,Starter作为SpringBoot的核心功能之一,基于自动配置代码提供了自动配置模块及依赖的能力,让软件集成变得简单、易用。使用SpringBoot时,我们只需引I人对应的Starter,SpringBoot启动时便会自动加载相关依赖,集成相关功能,这便是SpringBoot的自动装配功能。
简单概括其自动配置的原理:由@SpringBootAppliction组合注解中的@EnableAutoConfiguration注解开启自动配置,加载spring.factories文件中注册的各种默认定义的XxxAutoConfiguration配置类,并且该类可指定@Conditional条件注解,当其@Conditional条件注解生效时,实例化该配置类中定义的Bean,并注入Spring上下文。

一、自动配置核心机制

1. @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 {// ...
}

其中最关键的是@EnableAutoConfiguration注解。

2. @EnableAutoConfiguration注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {// ...
}

这个注解通过@Import导入了AutoConfigurationImportSelector类,这是自动配置的核心实现类。

二、自动配置核心流程

1. AutoConfigurationImportSelector

AutoConfigurationImportSelector实现了DeferredImportSelector接口,它的核心方法是selectImports()

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

关键调用链:

  1. getAutoConfigurationEntry()

  2. getCandidateConfigurations()

  3. loadFactoryNames()

  4. loadSpringFactories()

2. 加载自动配置类

loadSpringFactories()方法中,会从META-INF/spring.factories文件中加载配置:

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {// ...Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);// ...
}

FACTORIES_RESOURCE_LOCATION常量的值为"META-INF/spring.factories"

3. spring.factories文件

以spring-boot-autoconfigure模块为例,它的META-INF/spring.factories文件中定义了大量的自动配置类:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
...

三、条件化自动配置

Spring Boot自动配置的核心思想是"条件化配置",通过一系列@Conditional注解实现。

1. 常用条件注解

  • @ConditionalOnClass:类路径下存在指定类时生效

  • @ConditionalOnMissingClass:类路径下不存在指定类时生效

  • @ConditionalOnBean:容器中存在指定Bean时生效

  • @ConditionalOnMissingBean:容器中不存在指定Bean时生效

  • @ConditionalOnProperty:配置文件中存在指定属性时生效

  • @ConditionalOnResource:类路径下存在指定资源时生效

  • @ConditionalOnWebApplication:是Web应用时生效

  • @ConditionalOnNotWebApplication:不是Web应用时生效

2. 条件注解实现原理

@ConditionalOnClass为例,其实现类是OnClassCondition

@Order(Ordered.HIGHEST_PRECEDENCE)
class OnClassCondition extends FilteringSpringBootCondition {@Overrideprotected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,AutoConfigurationMetadata autoConfigurationMetadata) {// ...ConditionOutcome outcome = getOutcome(metadata);// ...}private ConditionOutcome getOutcome(ConditionMetadata metadata) {// 检查类是否存在ClassLoader classLoader = getClass().getClassLoader();String[] onClasses = metadata.getConditionalOnClass();for (String onClass : onClasses) {if (!ClassUtils.isPresent(onClass, classLoader)) {return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class).didNotFind("required class").items(Style.QUOTE, onClass));}}return null;}
}

四、自动配置执行流程

  1. 启动阶段

    • SpringApplication.run()启动应用

    • 调用refreshContext()刷新应用上下文

  2. 配置类解析

    • ConfigurationClassPostProcessor处理所有配置类

    • 解析@SpringBootApplication和@EnableAutoConfiguration

  3. 自动配置类加载

    • AutoConfigurationImportSelector加载spring.factories中的配置类

    • 过滤掉不满足条件的配置类

  4. Bean定义注册

    • 将筛选后的自动配置类注册为Bean定义

    • 后续由Spring容器实例化这些Bean

五、自动配置示例分析

以DataSourceAutoConfiguration为例:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {@Configuration(proxyBeanMethods = false)@Conditional(EmbeddedDatabaseCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import(EmbeddedDataSourceConfiguration.class)protected static class EmbeddedDatabaseConfiguration {}@Configuration(proxyBeanMethods = false)@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class,DataSourceConfiguration.Generic.class,DataSourceJmxConfiguration.class })protected static class PooledDataSourceConfiguration {}// ...
}

这个自动配置类展示了典型的条件化配置:

  1. 只有在类路径下存在DataSource和EmbeddedDatabaseType时才生效

  2. 容器中没有ConnectionFactory时才生效

  3. 根据不同的条件导入不同的配置

六、自动配置调试技巧

  1. 查看生效的自动配置
    在application.properties中添加:

    debug=true

    启动时会输出所有自动配置类的评估结果。

  2. 排除特定自动配置

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
  3. 查看自动配置条件
    通过/actuator/conditions端点(需要actuator依赖)可以查看详细的自动配置条件评估报告。

七、自定义自动配置

  1. 创建META-INF/spring.factories文件

  2. 定义自己的自动配置类

  3. 使用合适的条件注解

@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyServiceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService myService(MyServiceProperties properties) {return new MyService(properties);}
}

spring.factories中注册:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyServiceAutoConfiguration

八、自动配置的底层原理总结

  1. SPI机制:通过META-INF/spring.factories实现扩展点加载

  2. 条件评估:通过Condition接口实现条件化配置

  3. 延迟加载:通过DeferredImportSelector实现配置类的延迟处理

  4. 配置优先级:通过@AutoConfigureOrder@Order控制配置顺序

Spring Boot的自动配置机制通过这种灵活的条件化方式,既保证了"约定优于配置"的便利性,又提供了足够的灵活性来覆盖默认行为。

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

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

相关文章

音视频中一些常见的知识点

1. GCC是如何进行带宽评估的 GCC(Google Congestion Control)是一种专为实时音视频传输设计的拥塞控制算法,它主要通过发送端和接收端的协同工作来进行带宽评估。具体过程如下: 接收端处理 计算延迟梯度:接收端通过统计数据包到达时间的变化,即RTT(往返时间)波动,来计…

STM32硬件I2C的注意事项

文章目录软件模拟I2C硬件的实现方式最近在研究I2C的屏幕使用。有两种使用方式&#xff0c;软件模拟I2C、硬件HAL使用I2C。软件模拟I2C 发送数据是通过设置引脚的高低电平实现的。 /*引脚配置*/ #define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(x)) #de…

Python捕获异常

Python捕获异常主要通过try-except语句实现&#xff0c;以下是核心语法和使用场景&#xff1a;一、基础捕获结构try: # 可能引发异常的代码 result 10 / 0 except ZeroDivisionError: # 处理特定异常 print("除数不能为零") 二、捕获多种异常try: # 可能引发…

Scala 和 Spark 大数据分析(六)

原文&#xff1a;annas-archive.org/md5/39eecc62e023387ee8c22ca10d1a221a 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十三章&#xff1a;我的名字是贝叶斯&#xff0c;朴素贝叶斯 “预测是非常困难的&#xff0c;尤其是当它涉及未来时” -尼尔斯玻尔 机器学…

【kubernetes】-6污点与污点容忍

文章目录污点与污点容忍1、 污点&#xff08;taint&#xff09;2、操作命令3、污点容忍4、污点扩展污点与污点容忍 1、 污点&#xff08;taint&#xff09; 污点是节点的属性&#xff0c;用于排斥一类特定的 Pod。通过污点&#xff0c;可以避免 Pod 被调度到不合适的节点上 …

定义损失函数并以此训练和评估模型

基础神经网络模型搭建 【Pytorch】数据集的加载和处理&#xff08;一&#xff09; 【Pytorch】数据集的加载和处理&#xff08;二&#xff09; 损失函数计算模型输出和目标之间的距离。通过torch.nn 包可以定义一个负对数似然损失函数&#xff0c;负对数似然损失对于训练具有多…

电子书转PDF格式教程,实现epub转PDF步骤

EPUB 格式属于流式文档&#xff0c;在屏幕尺寸各异的设备上都能自动适配显示。然而&#xff0c;要是你使用的是特定的阅读设备&#xff0c;像打印机、不支持 EPUB 格式的电子阅读器&#xff08;例如某些早期的 Kindle 型号&#xff09;&#xff0c;或者需要在固定尺寸的屏幕上展…

Java学习第六十九部分——RabbitMQ

目录 一、前言提要 二、基本信息 1. 关键定义 2. 核心角色 3. 交换机类型 三、消息生命周期与可靠性机制 四、生态集成——与Java 五、应用场景 六、性能与选型对比 七、生产级最佳实践——基于Java 八、应用场景 九、一句话总结 一、前言提要 Spring AMQP是…

MDAC2.6问题解决指南:解决.NET Framework数据访问烦恼

MDAC2.6问题解决指南&#xff1a;解决.NET Framework数据访问烦恼 【下载地址】MDAC2.6问题解决指南 MDAC 2.6 问题解决指南为您提供了针对.NET Framework数据提供程序要求使用Microsoft Data Access Components (MDAC) 2.6或更高版本的全面解决方案。本指南详细介绍了如何在开…

会话跟踪模式

一、图片讲了什么&#xff1f;这张图片主要讲的是“会话跟踪技术”&#xff0c;也就是网站怎么记住你是谁、你做了什么。1. 什么是会话&#xff1f;会话&#xff08;Session&#xff09;就像你和网站的一次聊天&#xff0c;从你打开网页到关闭网页&#xff0c;这段时间就是一次…

C语言开发工具Win-TC

如你所知&#xff0c;WIN-TC是一个turbo C2 WINDOWS 平台开发工具&#xff0c;最大特点是支持中文界面&#xff0c;支持鼠标操作&#xff0c;程序段复制&#xff0c;为初学 c 语言、对高等编程环境不熟悉的同志们非常有帮助。该软件使用 turbo C2 为内核&#xff0c;提供 WINDO…

lwIP学习记录5——裸机lwIP工程学习后的总结

1、ping包的TTL生存时间如何修改当我们把工程烧录到板子上是&#xff0c;我们对板子的IP进行ping包&#xff0c;看到信息如下图这时候我好奇TTL是什么作用&#xff0c;为什么有的设备是64有的设备是128有的是255&#xff1f;解&#xff1a;TTL&#xff08;Time to Live&#xf…

利用Trae将原型图转换为可执行的html文件,感受AI编程的魅力

1、UI设计原型效果2、通过Tare对话生成的效果图&#xff08;5分钟左右&#xff09;3、查资料做的效果图&#xff08;30分钟左右&#xff09;&#xff09;通过以上对比&#xff0c;显然差别不多能满足要求&#xff0c;只需要在继续优化就能搞定&#xff1b; 4、Trae生成的源码&l…

Chessboard and Queens

题目描述Your task is to place eight queens on a chessboard so that no two queens are attacking each other. As an additional challenge, each square is either free or reserved, and you can only place queens on the free squares. However, the reserved squares …

菜鸟教程R语言一二章阅读笔记

菜鸟教程R语言一二章阅读笔记 一.R语言基础教程 R 语言是为数学研究工作者设计的一种数学编程语言&#xff0c;主要用于统计分析、绘图、数据挖掘。侧重于数学工作者 R语言特点如下&#xff1a; R 语言环境软件属于 GNU 开源软件&#xff0c;兼容性好、使用免费 语法十分有利于…

Tactile-VLA:解锁视觉-语言-动作模型的物理知识,实现触觉泛化

25年7月来自清华、中科大和上海交大的论文“Tactile-VLA: Unlocking Vision-Language- Action Model’s Physical Knowledge For Tactile Generalization ”。 视觉-语言-动作 (VLA) 模型已展现出卓越的成就&#xff0c;这得益于其视觉-语言组件丰富的隐性知识。然而&#xff0…

HTML初学者第五天

<1>表格标签1.1基本语法<table><tr><td>单元格内的文字</td>...</tr>... </table>1.<table></table>是用于定义表格的标签。2.<tr></tr>标签用于定义表格中的行&#xff0c;必须嵌套在<table></ta…

FastAPI入门:demo、路径参数、查询参数

demo from fastapi import FastAPIapp FastAPI()app.get("/") async def root():return {"message": "Hello World"}在终端运行 fastapi dev main.py结果如下&#xff1a;打开http://127.0.0.1:8000&#xff1a;交互式API文档&#xff1a;位于h…

pytest中的rerunfailures的插件(失败重试)

目录 1-- 安装rerunfailures插件 2-- rerunfailures的使用 3-- 重试案例 安装rerunfailures插件 pip install pytest-rerunfailures点击左下角的控制台面板 输入 pip install pytest-rerunfailures 出现上图的情况就算安装完成了 rerunfailures的使用 可以添加一下参数使用&…

SpringMVC——建立连接

建立连接 将用户&#xff08;浏览器&#xff09;和java程序连接起来&#xff0c;也就是访问一个地址能够调用到我们的Spring程序。在 Spring MVC 中使用 RequestMapping来实现URL 路由映射&#xff0c;也就是浏览器连接程序的作用。 1.RequestMapping注解介绍 RequestMapping…