Spring Boot自动配置原理深度解析:从条件注解到spring.factories

大家好!今天我们来深入探讨Spring Boot最神奇的特性之一——自动配置(Auto-configuration)。这个功能让Spring Boot如此受欢迎,因为它大大简化了我们的开发工作。让我们一起来揭开它的神秘面纱吧!👀

🌟 什么是自动配置?

想象一下,你刚搬进一个新家🏠。如果是传统Spring,你需要自己买家具、安装电器、布置每个房间。而Spring Boot就像一家提供"精装修"服务的公司——当你搬进去时,冰箱🍔、洗衣机👕、电视📺都已经安装好了,而且都是根据你的生活习惯智能选择的!

这就是自动配置的魔力✨——它根据你项目中的依赖和配置,自动为你配置好Spring应用所需的大部分组件。

�️ 自动配置的核心原理

自动配置的实现依赖于几个关键技术和概念:

1. @EnableAutoConfiguration注解

这是启动自动配置的"开关"🔛。当你在主类上使用@SpringBootApplication时,它实际上包含了@EnableAutoConfiguration

@SpringBootApplication  // 这里面就包含了@EnableAutoConfiguration
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}

2. spring.factories文件

这是自动配置的"地图"🗺️。Spring Boot在META-INF/spring.factories文件中查找所有自动配置类。

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration,\
com.example.AnotherAutoConfiguration

3. 条件注解(Conditional Annotations)

这些是自动配置的"决策大脑"🧠,决定是否应该应用某个配置。常见的条件注解包括:

  • @ConditionalOnClass:当类路径上有指定类时生效
  • @ConditionalOnMissingBean:当容器中没有指定Bean时生效
  • @ConditionalOnProperty:当配置属性满足条件时生效
  • @ConditionalOnWebApplication:当是Web应用时生效

🔬 深入自动配置流程

让我们看看Spring Boot是如何实现自动配置的:

  1. 启动阶段🚦:

    • Spring Boot应用启动
    • @SpringBootApplication触发自动配置
  2. 加载自动配置类📦:

    • Spring Boot扫描所有jar包中的META-INF/spring.factories文件
    • 加载org.springframework.boot.autoconfigure.EnableAutoConfiguration键下所有的配置类
  3. 过滤自动配置类🧹:

    • 根据各种条件注解过滤掉不适用的配置类
    • 只保留符合条件的配置类
  4. 应用配置⚙️:

    • 将最终筛选出的配置类应用到Spring容器中
    • 创建并注册各种Bean

🧩 条件注解详解

条件注解是自动配置的核心机制,让我们详细看看几个重要的:

@ConditionalOnClass

@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {// 只有当DataSource类在类路径上时,这个配置才会生效
}

@ConditionalOnMissingBean

@Bean
@ConditionalOnMissingBean
public MyService myService() {// 只有当容器中没有MyService类型的Bean时,才会创建这个默认的MyServicereturn new DefaultMyService();
}

@ConditionalOnProperty

@Configuration
@ConditionalOnProperty(prefix = "myapp", name = "enabled", havingValue = "true")
public class MyAppAutoConfiguration {// 只有当myapp.enabled=true时,这个配置才会生效
}

@ConditionalOnWebApplication

@Configuration
@ConditionalOnWebApplication
public class WebMvcAutoConfiguration {// 只有当应用是Web应用时,这个配置才会生效
}

🛠️ 自动配置实战:自定义Starter

理解了原理后,让我们动手创建一个自定义的Spring Boot Starter!

1. 创建自动配置模块

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

2. 创建配置属性类

@ConfigurationProperties("my.service")
public class MyServiceProperties {private String prefix;private String suffix;// getters and setters
}

3. 注册自动配置类

src/main/resources/META-INF/下创建spring.factories文件:

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

4. 打包发布

现在,其他项目只需要引入你的starter依赖,就可以自动获得MyService的配置了!

🔍 自动配置的调试技巧

有时候我们需要了解为什么某个自动配置没有生效,Spring Boot提供了几种调试方式:

  1. 启用调试日志📝:
    application.properties中添加:

    debug=true
    

    启动时会打印自动配置报告。

  2. 使用ConditionEvaluationReport📊:
    可以通过注入ConditionEvaluationReport来获取详细的条件评估报告。

  3. 使用Spring Boot Actuator👨⚕️:
    /actuator/conditions端点提供了详细的自动配置条件信息。

⚖️ 自动配置的优缺点

优点:

  • 快速启动⚡:无需手动配置大量样板代码
  • 一致性🔄:所有项目使用相同的默认配置
  • 灵活性🧘:可以通过属性文件轻松覆盖默认配置
  • 模块化🧩:每个starter提供一组相关的自动配置

缺点:

  • 黑盒效应📦:新手可能不理解背后的机制
  • 调试困难🐛:当自动配置不符合预期时,可能需要深入理解原理
  • 启动时间⏳:评估大量条件注解可能增加启动时间

🎓 最佳实践

  1. 理解默认配置🧠:
    在使用一个starter前,最好了解它提供了哪些自动配置。

  2. 合理覆盖配置⚖️:
    只在必要时覆盖自动配置,保持一致性。

  3. 创建自己的starter🛠️:
    当有一组相关的配置和Bean时,考虑创建自己的starter。

  4. 利用条件注解🎚️:
    在自己的配置中也使用条件注解,使配置更加灵活。

  5. 监控自动配置👀:
    定期检查自动配置报告,确保配置符合预期。

🌰 实际案例:DataSource自动配置

让我们看一个实际的自动配置例子——DataSourceAutoConfiguration

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {@Configuration@Conditional(EmbeddedDatabaseCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import(EmbeddedDataSourceConfiguration.class)protected static class EmbeddedDatabaseConfiguration {}@Configuration@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class,DataSourceConfiguration.Generic.class })protected static class PooledDataSourceConfiguration {}// ...
}

这个自动配置类展示了几个关键点:

  1. 只有在类路径上有DataSourceEmbeddedDatabaseType时才生效
  2. 导入了属性配置DataSourceProperties
  3. 根据条件选择嵌入式数据库或连接池数据库
  4. 支持多种连接池实现(Hikari, Tomcat, Dbcp2等)

🕵️ 如何查看生效的自动配置

Spring Boot提供了几种方式来查看哪些自动配置生效了:

  1. 使用Actuator

    curl http://localhost:8080/actuator/conditions
    
  2. 启用调试模式
    在application.properties中添加:

    debug=true
    

    启动时会打印自动配置报告。

  3. 使用Spring Boot Tools
    许多IDE(如IntelliJ IDEA)提供了Spring Boot工具窗口,可以查看自动配置。

🔄 自动配置与显式配置的关系

自动配置并不是要完全取代显式配置,而是与之协同工作:

  1. 自动配置先执行🏃‍♂️:
    Spring Boot会先尝试自动配置

  2. 显式配置可以覆盖自动配置🖌️:
    你的@Bean定义会覆盖自动配置提供的Bean

  3. 条件注解确保灵活性⚖️:
    自动配置通常带有@ConditionalOnMissingBean,允许你提供自己的实现

🧪 测试自动配置

测试自动配置需要特殊考虑:

  1. 使用@SpringBootTest

    @SpringBootTest
    public class MyAutoConfigurationTests {@Autowired(required = false)private MyService myService;@Testpublic void testServiceAutoConfigured() {assertNotNull(myService);}
    }
    
  2. 测试特定条件

    @Test
    public void testConditionalOnClass() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();EnvironmentTestUtils.addEnvironment(context, "some.property:true");context.register(MyAutoConfiguration.class);context.refresh();assertTrue(context.containsBean("myBean"));
    }
    

🚀 性能优化技巧

自动配置虽然方便,但也可能影响启动性能:

  1. 减少不必要的starter✂️:
    只引入真正需要的starter依赖

  2. 延迟初始化⏸️:
    在application.properties中设置:

    spring.main.lazy-initialization=true
    
  3. 使用@ComponentScan限制🎯:
    精确指定扫描路径,避免不必要的类扫描

  4. 排除自动配置🚫:
    使用@SpringBootApplication的exclude属性:

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    

📚 深入学习资源

如果你想更深入地学习Spring Boot自动配置:

  1. 官方文档📄:
    Spring Boot Auto-configuration Docs

  2. 源码学习👨💻:
    阅读spring-boot-autoconfigure模块的源码

  3. 相关技术🔗:

    • Spring Framework的@Conditional机制
    • Spring的Environment抽象
    • Spring的BeanDefinition体系

🎯 总结

Spring Boot的自动配置是一个强大而复杂的系统,它通过以下方式工作:

  1. 使用@EnableAutoConfiguration触发自动配置过程
  2. 通过spring.factories发现所有潜在的自动配置类
  3. 利用各种条件注解过滤出适用的配置
  4. 将最终筛选出的配置应用到Spring容器中

理解自动配置原理不仅能帮助你更好地使用Spring Boot,还能让你在遇到问题时更快地定位和解决。希望这篇文章能帮助你深入理解这个强大的特性!💪

记住,自动配置的目标是约定优于配置——它提供了一套合理的默认值,但你总是可以根据需要覆盖这些默认值。这就是Spring Boot既强大又灵活的秘密所在!🔑

Happy coding! 🚀👨💻

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

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

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

相关文章

【ELF2学习板】利用OpenMP采用多核并行技术提升FFTW的性能

目录 引言 OpenMP简介 编译OpenMP支持的FFTW库 部署与测试 测试程序 程序部署 测试结果 结语 引言 在前面已经介绍了在ELF2开发板上运行FFTW计算FFT。今天尝试利用RK3588的多核运算能力来加速FFT运算。FFTW利用多核能力可以考虑使用多线程或者OpenMP。今天介绍一下Ope…

2000-2017年各省城市天然气供气总量数据

2000-2017年各省城市天然气供气总量数据 1、时间:2000-2017年 2、来源:国家统计局、能源年鉴 3、指标:行政区划代码、城市、年份、城市天然气供气总量 4、范围:31省 5、指标说明:城市天然气供气总量是指在一定时间…

Hadoop的三大结构及其作用?

Hadoop是一个分布式存储和计算框架,其三大核心组件是HDFS(Hadoop Distributed File System)、YARN(Yet Another Resource Negotiator)和MapReduce。它们各自有着重要的作用,共同构成了Hadoop生态系统的基础…

【AI论文】ColorBench:视觉语言模型能否看到并理解多彩的世界?一个全面的色彩感知、推理和鲁棒性基准测试

摘要:颜色在人类感知中起着重要作用,通常在视觉推理中提供关键线索。 然而,尚不清楚视觉语言模型(VLMs)是否以及如何像人类一样感知、理解和利用颜色。 本文介绍了ColorBench,这是一个精心设计的创新基准&a…

Python番外——常用的包功能讲解和分类组合

目录 1. Web开发框架与工具 2. 数据处理与分析 3. 网络请求与爬虫 4. 异步编程 5. 数据库操作 6. 图像与多媒体处理 7. 语言模型与NLP 8. 安全与加密 9. 配置与工具 10. 其他工具库 11.典型组合场景 此章节主要是记录我所使用的包,以及模块。方便供自己方…

华硕原厂系统枪神9/9p超竟版-WIN11原装开箱出厂系统安装

华硕原厂系统枪神9/9p超竟版-WIN11-24H2-专业工作站版本安装可带F12-ASUSRecovery恢复功能 适用机型: G635LX、G635LW、G835LX、G835LW、G615LW、G615LP、G615LM、G615LH G815LW、G815LP、G815LM、G815LH、G635LR、G835LR、G615LR、G815LR 远程恢复安装&#xff…

拉取windows的docker镜像转到服务器上构建服务镜像

在windows上将拉取ubuntu的docker镜像转到服务器上 1.要求 1.1 要求windows和服务器安装好docker 2.拉取ubuntu镜像到windows(dos操作,可能需要连接到外网) 一旦你选择了一个合适的基础镜像,你可以使用docker pull命令从Docke…

T1结构像+RS-fMRI影像处理过程记录(数据下载+Matlab工具箱+数据处理)

最近需要仿真研究T1结构像RS-fMRI影像融合处理输出目标坐标的路线可行性。就此机会记录下来。 为了完成验证目标处理,首先需要有数据,然后需要准备对应的处理平台和工具箱,进行一系列。那么开始记录~ 前言: 为了基于种子点的功能连…

Nginx-前言

nginx是什么? 轻量级,开源免费的web服务器软件,服务器安装nginx,服务器则成为web服务器 nginx的稳定版版本号: 偶数版本 nginx的相关目录: /etc/nginx/nginx.conf nginx的主配置文件 /etc/nginx/ngi…

缓慢前行,静待花开

最期待的不是成品出炉,而是揉面时感受到温度、发酵时闻到淡淡香气 1 “慢就是稳,稳就是快”。 这句来自特种兵的训练语,被许多自媒体人奉为准则。 在看似风云突变的环境下,速度被隐藏在稳定中,结果被酝酿在过程里。…

洛谷的几道题(2)

P1008 [NOIP 1998 普及组] 三连击 # P1008 [NOIP 1998 普及组] 三连击 ## 题目背景 本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序。 ## 题目描述 将 $1, 2, \ldots , 9$ 共 $9$ 个数分…

Day10【基于encoder- decoder架构实现新闻文本摘要的提取】

实现新闻文本摘要的提取 1. 概述与背景2.参数配置3.数据准备4.数据加载5.主程序6.预测评估7.生成效果8.总结 1. 概述与背景 新闻摘要生成是自然语言处理(NLP)中的一个重要任务,其目标是自动从长篇的新闻文章中提取出简洁、准确的摘要。近年来…

【大疆dji】ESDK开发环境搭建(软件准备篇)

接上一篇【大疆dji】ESDK开发环境搭建(硬件准备篇) 1. 编译环境 ESDK 提供 x86_64/aarch64 基于 Linux 平台 Ubuntu 发行版操作系统构建的静态库,运行 demo 先正确安装所需的依赖包。arm32位就不支持了。建议使用编译安装的方式,…

Java数据结构——ArrayList

Java中ArrayList 一 ArrayList的简介二 ArrayList的构造方法三 ArrayList常用方法1.add()方法2.remove()方法3.get()和set()方法4.index()方法5.subList截取方法 四 ArrayList的遍历for循环遍历增强for循环(for each)迭代器遍历 ArrayList问题及其思考 前言 ArrayList是一种 顺…

【信息获取能力】

第一层:表象观察 现象:AI系统(如GPT-4)可以瞬间调用并整合全球互联网上的公开信息,而人类即使穷尽一生也无法完成同等规模的知识储备。 底层逻辑: 存储与检索效率:人类大脑的记忆容量有限&…

03、GPIO外设(三):标准库代码示例

标准库代码示例 1、点亮LED2、LED闪烁3、LED流水灯4、按键控制LED5、蜂鸣器 本章源代码链接: 链接: link 1、点亮LED 实验要求:点亮LED ①LED.c文件的代码如下: #include "LED.h"/*** LED引脚初始化*//* 定义数组,想要添加引脚…

卷积神经网络(CNN)与VGG16在图像识别中的实验设计与思路

卷积神经网络(CNN)与VGG16在图像识别中的实验设计与思路 以下从基础原理、VGG16架构解析、实验设计步骤三个层面展开说明,结合代码示例与关键参数设置,帮助理解其应用逻辑。 一、CNN与VGG16的核心差异 基础CNN结构 通常包含33~55个…

java导出word含表格并且带图片

背景 我们需要通过 Java 动态导出 Word 文档,基于预定义的 模板文件(如 .docx 格式)。模板中包含 表格,程序需要完成以下操作: 替换模板中的文本(如占位符 ${设备类型} 等)。 替换模板中的图…

Oracle19C低版本一天遭遇两BUG(ORA-04031/ORA-600)

昨天帮朋友看一个系统异常卡顿的案例,在这里分享给大家 环境:Exadata X8M 数据库版本19.11 1.系统报错信息 表象为系统卡顿,页面无法刷出,登陆到主机上看到节点1 系统等待存在大量的 cursor: pin S wait on X等待 查看两个节…

2025年Q1数据安全政策、规范、标准以及报告汇总共92份(附下载)

一、政策演进趋势分析 (一)国家级政策新动向 数据要素市场建设 数据流通安全治理方案(重点解析数据确权与交易规则) 公共数据授权运营规范(创新性提出分级授权机制) 新兴技术安全规范 人工智能安全标准…