SpringBoot 自动装配原理及源码解析

news2025/2/25 11:30:57

目录

一、引言

二、什么是 Spring Boot 的自动装配

三、自动装配的核心注解解析

3.1 @SpringBootApplication 注解

(1)@SpringBootConfiguration:

(2)@EnableAutoConfiguration:

(3)@ComponentScan:

3.2 条件装配(@Conditional 系列注解)

示例:DataSourceAutoConfiguration

四、自动配置的工作流程

五、SpringBoot 自动装配的实际案例

六、好处


一、引言

        在 Java 开发领域,Spring Boot 占据着重要地位,其自动装配机制对传统开发模式产生了巨大变革。过去,传统 Spring 项目配置繁杂,极易出现版本冲突与配置错误,耗费开发者大量精力。而 Spring Boot 引入自动装配功能后,项目近乎可 “零配置” 启动,开发者能将主要精力集中于业务逻辑的实现,极大提高了开发效率。接下来,我们深入剖析 Spring Boot 自动装配背后的原理。

二、什么是 Spring Boot 的自动装配

        Spring Boot 自动装配是一套智能且高效的依赖注入与配置协调系统,遵循 “约定优于配置” 的原则。在项目启动阶段,它能够自动识别类路径下的各类组件及配置信息,并依据预先设定的精细规则完成装配任务。

三、自动装配的核心注解解析

3.1 @SpringBootApplication 注解

自动配置的起点通常是 @SpringBootApplication 注解,它是一个组合注解,包含了三个重要注解。

@SpringBootApplication
public class SpringBootDemo1031Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemo1031Application.class, args);
    }
}

(1)@SpringBootConfiguration

本质等同于@Configuration,为自动装配的配置环节搭建基础框架,保障配置步骤有序进行

(2)@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

        它是是自动配置的核心,通过@Import(AutoConfigurationImportSelector.class)引入AutoConfigurationImportSelector。

AutoConfigurationImportSelector 类的继承体系如下:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

}

public interface DeferredImportSelector extends ImportSelector {

}

public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}

        可以看出,AutoConfigurationImportSelector类实现了ImportSelector接口,也就实现了这个接口中的selectImports方法,该方法主要用于获取所有符合条件的类的全限类名,这些类需要被加载到IOC容器中。 

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 1.检查是否启用自动配置
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
        // 2.获取所有需要装配的bean
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
}

getAutoConfigurationEntry方法通过一系列步骤,包括检查自动配置是否启用、获取候选配置、去除重复项、获取排除配置、检查排除的类是否有效、移除排除项、过滤配置,最终生成一个包含自动配置类和排除配置类的AutoConfigurationEntry对象。这个方法是Spring Boot自动配置功能的核心,它确保了只有符合条件的自动配置类被加载到Spring应用上下文中。

/**
 * 获取自动配置入口信息,包括需要加载的自动配置类和需要排除的配置类。
 *
 * @param annotationMetadata 当前注解的元数据,提供了关于注解的信息,用于决定哪些自动配置类应该被导入。
 * @return 包含自动配置类和排除配置类的AutoConfigurationEntry对象。
 */
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    // 1. 如果自动配置没有被启用,则返回一个空的AutoConfigurationEntry对象
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
        // 2. 从注解元数据中获取注解属性
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        // 3. 获取所有候选的自动配置类名
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        // 4. 去除候选配置中的重复项
        configurations = this.removeDuplicates(configurations);
        // 获取需要被排除的自动配置类名
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        // 检查排除的类是否在候选配置中,如果不在,则抛出异常
        this.checkExcludedClasses(configurations, exclusions);
        // 从候选配置中移除排除项
        configurations.removeAll(exclusions);
        // 使用ConfigurationClassFilter过滤候选配置
        configurations = this.getConfigurationClassFilter().filter(configurations);
        // 触发自动配置导入事件,通知所有监听器自动配置类即将被导入
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        // 创建并返回一个新的AutoConfigurationEntry对象,包含过滤后的配置和排除配置
        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
}

接下来,我们debug看一下具体步骤:

  • 步骤1:判断自动装配开关是否打开,默认spring.boot.enableautoconfiguration=true,可以在application.properties或者application.yml中设置 。
  • 步骤2:获取EnableAutoConfiguration注解中的exclude 和excluedeName

  • 步骤3:获取需要自动装配的所有配置类,读取META-INF/spring.factories 

自动配置类的信息通常位于spring-boot-autoconfigure模块的META-INF/spring.factories文件中。这个文件列出了所有可以被自动加载的配置类,当Spring Boot应用启动时,AutoConfigurationImportSelector会读取这个文件,并根据其中的信息将相应的自动配置类导入到应用上下文中。

  • 步骤4:在spring boot中,spring.factories文件中列出了许多自动配置类,这并不意味着每次应用启动时所有这些配置都会被加载。Spring Boot采用一种称为条件配置的机制,使得只有在特定条件满足时,相关的自动配置类才会被激活和加载。

(3)@ComponentScan

        负责搜索项目中的组件,收集散落的组件,为后续装配工作提供资源支持,确保所需组件无遗漏。

3.2 条件装配(@Conditional 系列注解)

Spring Boot并非盲目加载所有自动配置类,每个自动配置类通常都会运用@Conditional系列注解来实现有条件的加载,这极大地优化了资源配置,让自动装配更贴合项目实际需求。最常见的条件注解有:

  • @ConditionalOnClass:当类路径中存在某个类时才生效。
  • @ConditionalOnMissingBean:当 Spring 上下文中不存在某个 Bean 时才生效。
  • @ConditionalOnProperty:当某个配置属性满足特定条件时才生效。
  • @ConditionalOnBean:当 Spring 上下文中存在某个 Bean 时才生效。

示例:DataSourceAutoConfiguration

Spring Boot 中DataSourceAutoConfiguration 是配置数据源的自动配置类,它的源码如下:

@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({DataSourcePoolMetadataProvidersConfiguration.class,
         DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {
 
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }
}
  • @ConditionalOnClass(DataSource.class):只有当类路径下存在 DataSource 类时,才进行数据源的自动配置。
  • @ConditionalOnMissingBean:如果 Spring 上下文中没有其他 DataSource Bean,则自动配置一个。

        只有当这些条件满足时,DataSourceAutoConfiguration才会被实例化和执行,这意味着Spring Boot在启动过程中,并不会盲目的加载spring.factories中的每一个自动配置类,而是基于运行环境和应用的配置智能选择激活配置。

四、自动配置的工作流程

1. 收集自动配置类

启动时,AutoConfigurationImportSelector 从 spring.factories 文件中读取所有的自动配置类,并通过 @Import 导入这些类。

2. 条件检查

自动配置类的加载不是无条件的,Spring Boot 会根据 @Conditional 注解进行条件检查,确保只有符合条件的自动配置类才会生效。

3. 注入所需的 Bean

一旦自动配置类通过条件检查,Spring Boot 就会根据这些配置类注册所需的 Bean。例如,DataSourceAutoConfiguration 会自动配置数据源相关的 Bean。

4. 允许用户覆盖自动配置

自动配置并不是强制的。用户可以通过显式声明自己的 Bean 来覆盖自动配置的默认行为。例如,如果用户在自己的配置类中定义了 DataSource,那么 Spring Boot 就不会再自动配置数据源。

五、SpringBoot 自动装配的实际案例

1. Web 应用自动配置

在 Spring Boot Web 应用中,DispatcherServletAutoConfiguration 负责自动配置 Spring MVC 的核心组件,例如 DispatcherServletRequestMappingHandlerMapping 等。

  • 如果项目中存在 spring-web 依赖,那么 DispatcherServletAutoConfiguration 会自动加载。
  • 如果没有手动定义 DispatcherServlet,Spring Boot 会自动创建一个 DispatcherServlet 并配置到 Spring 容器中。

2. 数据库连接池自动配置

Spring Boot 还会自动配置数据库连接池(如 HikariCP、Tomcat JDBC 等),这依赖于项目中的 spring-boot-starter-data-jpa 或者 spring-boot-starter-jdbc 依赖。

  • DataSourceAutoConfiguration 和 DataSourceProperties 共同负责自动配置数据源。
  • 如果类路径中存在连接池类(如 DruidDataSource),那么 Spring Boot 就会自动配置连接池。

六、好处

1. 提高开发效率

开发者摆脱繁琐配置工作,无需反复查阅文档、调试配置,节省大量时间,得以聚焦业务功能迭代,在市场竞争中抢占先机。

2. 降低学习成本

对于初涉 Spring 技术栈的新手,复杂的 Spring 配置体系曾令人望而却步。自动装配机制降低入门难度,使其无需陷入配置困境,轻松上手融入团队。

3. 保证一致性

自动装配由 Spring Boot 框架统一管理控制,遵循统一约定,不同项目结构与配置趋于一致,便于团队协作、代码维护与知识传承,保障项目生命周期稳健延续。

        总之,Spring Boot 自动装配机制为 Java 开发注入强大动力,深入理解其原理和流程,有助于开发者在开发领域游刃有余。后续可探索定制化自动装配,拓展框架应用边界,激发更多创新可能。

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

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

相关文章

2025系统架构师(一考就过):案例题之一:嵌入式架构、大数据架构、ISA

一、嵌入式系统架构 软件脆弱性是软件中存在的弱点(或缺陷)&#xff0c;利用它可以危害系统安全策略&#xff0c;导致信息丢失、系统价值和可用性降低。嵌入式系统软件架构通常采用分层架构&#xff0c;它可以将问题分解为一系列相对独立的子问题&#xff0c;局部化在每一层中…

单片机上电后程序不运行怎么排查问题?

1.电源检查。使用电压表测量单片机的电源电压是否正常&#xff0c;确保电压在规定的范围内&#xff0c;如常见的5V。 2.复位检查。检查复位引脚的电压是否正常&#xff0c;在单片机接通电源时&#xff0c;复位引脚通常会有一个高电平&#xff0c;按下复位按钮时&#xff0c;复位…

初学stm32 --- 外部中断

目录 STM32 IO 口中断基础知识 相关库函数&#xff1a; 使用 IO 口外部中断的一般步骤 STM32 IO 口中断基础知识 STM32 的每个 IO 都可以作为外部中断的中断输入口。STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位&#xff0c;每个中断/事件都有独立…

c++------------------函数

函数定义 语法格式 函数定义包括函数头和函数体。函数头包含返回类型、函数名和参数列表。函数体是用花括号{}括起来的代码块&#xff0c;用于实现函数的功能。例如&#xff0c;定义一个计算两个整数之和的函数&#xff1a; int add(int a, int b) {return a b; }这里int是返回…

【java基础系列】实现一个简单的猜数字小游戏

主要是用的java中的键盘录入和随机数两个api&#xff0c;实现这种人机交互的小游戏&#xff0c;可以用来锻炼基础算法思维 实现效果 实现代码 package com.gaofeng.day10;import java.util.Random; import java.util.Scanner;/*** author gaofeng* date 2024-12-22 - 9:21*/ …

helm的介绍和安装

1 helm概述 1.1 资源对象难以管理的问题 helm是k8s资源清单的管理工具&#xff0c;它就像Linux下的包管理器&#xff0c;比如centos的yum&#xff0c;ubuntu的apt helm&#xff1a;命令行工具&#xff0c;主要用于k8s的chart的创建&#xff0c;打包&#xff0c;发布和管理。…

AI,cursor快速上手思维导图

https://cursor101.com/zh/tutorial/learn-cursor-tab

ESP32S3 使用LVGL驱动LCD屏(ST7789主控)

ESP32S3 使用LVGL驱动LCD屏&#xff08;ST7789主控&#xff09; 目录 1 分析原理图 2 驱动、点亮LCD(ST7789) 2.1 在工程中添加目录、文件 2.2 添加esp_lvgl_port组件 2.3 对工程进行必要的配置 2.4 编写必要代码 3 烧录、验证 1 分析原理图 要使用SOC驱动LCD屏&#…

【hackmyvm】Zday靶机wp

HMVrbash绕过no_root_squash静态编译fogproject 1. 基本信息^toc 这里写目录标题 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描 3. fog project Rce3.1. ssh绕过限制 4. NFS no_root_squash5. bash运行不了怎么办 靶机链接 https://hackmyvm.eu/machines/machine.ph…

neo4j console 报错

项目场景&#xff1a; neo4j 开启失败 问题描述 在终端打开 neo4j 失败打开cmd, 输入: neo4j console 报错 原因分析&#xff1a; 1 可能是没有配置环境变量2 当前脚本的执行策略有问题 解决方案&#xff1a; 解决没有配置环境变量 添加环境变量 在path路径中将变量添加进去…

范德蒙矩阵(Vandermonde 矩阵)简介:意义、用途及编程应用

参考&#xff1a; Introduction to Applied Linear Algebra – Vectors, Matrices, and Least Squares Stephen Boyd and Lieven Vandenberghe 书的网站: https://web.stanford.edu/~boyd/vmls/ Vandermonde 矩阵简介&#xff1a;意义、用途及编程应用 在数学和计算科学中&a…

编译原理复习---正则表达式+有穷自动机

适用于电子科技大学编译原理期末考试复习。 1. 正则表达式 正则表达式&#xff08;Regular Expression&#xff0c;简称regex或regexp&#xff09;是一种用于描述、匹配和操作文本模式的强大工具。它由一系列字符和特殊符号组成&#xff0c;这些字符和符号定义了一种搜索模式…

CAD跨图纸复制与粘贴怎么操作?教程来了

在过去&#xff0c;图纸的复制粘贴工作大多依赖于电脑完成&#xff0c;手机则因运行内存等硬件限制&#xff0c;难以像电脑那样轻松实现多图同开&#xff0c;以及图纸内容的跨图复制粘贴。为解决这一痛点&#xff0c;CAD看图王手机端推出了跨图复制与粘贴功能&#xff0c;为用户…

算法训练第二十三天|93. 复原 IP 地址 78. 子集 90. 子集 II

93. 复原 IP 地址--分割 题目 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&…

Go怎么做性能优化工具篇之基准测试

一、什么是基准测试&#xff08;Benchmark&#xff09; 在 Go 中&#xff0c;基准测试是通过创建以 Benchmark 开头的函数&#xff0c;并接收一个 *testing.B 类型的参数来实现的。testing.B 提供了控制基准测试执行的接口&#xff0c;比如设置测试执行的次数、记录每次执行的…

【贪吃蛇小游戏 - JavaIDEA】基于Java实现的贪吃蛇小游戏导入IDEA教程

有问题请留言或私信 步骤 下载项目源码&#xff1a;项目源码 解压项目源码到本地 打开IDEA 左上角&#xff1a;文件 → 新建 → 来自现有源代码的项目 找到解压在本地的项目源代码文件&#xff0c;点击确定 选择“从现有项目创建项目”。点击“下一步” 点击下一步&a…

LabVIEW手机屏幕耐冲击测试

开发了一个基于LabVIEW的智能手机屏幕耐冲击测试系统。系统利用LabVIEW软件与高精度传感器&#xff0c;对手机屏幕进行落球冲击试验&#xff0c;以测定其耐冲击性能。这项技术不仅提高了测试的精度和效率&#xff0c;而且对智能手机屏幕的质量控制和改进提供了科学依据。 项目背…

Python + 深度学习从 0 到 1(01 / 99)

希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持&#xff01; ⭐ 深度学习之前&#xff1a;机器学习简史 什么要了解…

FPGA学习(基于小梅哥Xilinx FPGA)学习笔记

相关资源网站&#xff08;小梅哥FPGA&#xff09; https://www.corecourse.cn/forum.php?modviewthread&tid27978 https://www.corecourse.cn/forum.php?modviewthread&tid28730 本篇文章使用的开发板为&#xff1a; 小梅哥 Xilinx FPGA 型号&#xff1a;XC7A35T 芯…

网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析

国内外要闻 Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析 在网络安全的复杂战场中&#xff0c;近期出现了一个值得关注的动态&#xff1a;名为 Rockstar 2FA 的钓鱼即服务&#xff08;PhaaS&#xff09;工具包遭遇变故&#xff0c;意外推动了另一个新生服务 Flo…