当前位置: 首页 > news >正文

源码角度解析SpringBoot 自动配置

文章目录

  • 前言
  • 一、了解相关注解
    • 1.@Condition注解
    • 2.@Enable注解
  • 二、SpringBoot自动配置
    • 1.@SpringBootApplication注解
    • 2.@SpringBootConfiguration注解
    • 3.@EnableAutoConfiguration注解
    • 4.@Conditional注解
  • 总结


前言

Spring Boot 自动配置是 Spring Boot 的核心特性之一,它的目标是通过分析应用程序的类路径(classpath)和依赖关系,来自动配置 Spring 应用程序所需的 Bean、设置和组件。这意味着开发人员不需要手动配置大部分常见的 Spring 组件,Spring Boot 将根据环境和依赖来进行智能配置。这样,开发人员可以专注于编写业务逻辑,而不必过多关心底层配置细节。


一、了解相关注解

1.@Condition注解

Condition 是在Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 操作。
SpringBoot 提供的常用条件注解:

  • @ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
  • @ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
  • @ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
  • @ConditionalOnBean:判断环境中有对应Bean才初始化Bean

2.@Enable注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注 解导入一些配置类,实现Bean的动态加载。
@Enable底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用法:​
① 导入Bean;
@Import(User.class)
② 导入配置类;
@Import(UserConfig.class)
③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类;
@Import(MyImportSelector.class)
④ 导入 ImportBeanDefinitionRegistrar 实现类。
@Import({MyImportBeanDefinitionRegistrar.class})

二、SpringBoot自动配置

1.@SpringBootApplication注解

主启动类注解:

package org.springframework.boot.autoconfigure;
@Targer(ElementType.TYPE)//作用于类
@Retention(Retention.RUNTIME)//该注解在运行时可见,可以通过反射读取
@Documented//文档相关
@Inherited//可以被子类继承
@SpringBootConfiguration//标记该类为 Spring Boot 的配置类
@EnableAutoConfiguration//实现自动配置功能
@ComponentScan(excludeFilters = {@Filter(type=FilterType.CUSTOM,classes = TypeExcludeFilter.class),@Filter(type=FilterType.CUSTOM,classes = AutoConfigurationExcludeFilter.class)
})//配置组件扫描,以查找和注册 Spring Bean
public @interface SpringBootApplication{……}

总的来说,大概可以把@SpringBootApplication看作是@Configuration、@EnableAutoConfigeration、@ComponentScan注解的集合。
@EnableAutoConfigeration:启用SpringBoot的自动配置机制;
@ComponentScan:扫描被@Component(@Service,@Controller)注解的bean,注解默认会扫描该类所在包下的所有的类;
@Configuration:允许在上下文中注册额外的bean或倒入其他配置类。

2.@SpringBootConfiguration注解

SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;

//这里的@Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
@Configuration
public @interface SpringBootConfiguration {}
//里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用
@Component
public @interface Configuration {....}

3.@EnableAutoConfiguration注解

@EnableAutoConfiguration开启自动配置功能,它可以说是我们研究SpringBoot 自动配置的重中之重了:

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

3.1@AutoConfigurationPackage注解:

//AutoConfigurationPackage的子注解
//Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}

在默认的情况下就是将:主配置类(@SpringBootApplication)的所在包及其子包里边的组件扫描到Spring容器中。

3.2@Import({AutoConfigurationImportSelector.class})注解:给容器导入组件
AutoConfigurationImportSelector :自动配置导入选择器,给容器中导入一些组件;
通过了@import注解导入了AutoConfigurationImportSelector这个配置类,根据类名可以发现,这个实现类是@Import提供4中用法中的ImportSelector的实现类,那么它就一定实现了selectImports这个个方法

String[] selectImports(AnnotationMetadata importingClassMetadata);

该方法的主要目的是根据运行时的条件或配置动态地确定要导入哪些配置类,以扩展或自定义 Spring 应用程序的配置。
返回值是一个字符串数组,其中包含需要导入到当前配置类中的其他配置类的全限定类名。
那我们就来看看他是怎么来重写这个方法的:

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

this.isEnabled(annotationMetadata) 方法检查是否启用了自动配置。如果没有启用,就返回一个空数组 NO_IMPORTS,表示不导入任何配置类。
getAutoConfigurationEntry(annotationMetadata) 方法来获取自动配置入口,那么他是如何去获取的呢?继续进方法看看:

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

用于根据给定的注解元数据 (annotationMetadata) 和属性 (attributes) 获取潜在的自动配置类的列表,它的作用就是找到所有可能与应用程序上下文相关的自动配置类。
↓ ↓ ↓

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");return configurations;}

这个方法想告诉我们什么呢,其实看到这里官方给出的提示就已经很明显了:

在META-INF/spring中找不到自动配置类。在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中。如果您正在使用自定义打包,请确保该文件是正确的。

简但来说,就是在所有包名叫做autoConfiguration的包下面都有META-INF/spring.factories文件,Spring启动的时候会扫描这个文件,将其文件包装成Properties对象从Properties对象获取到key值为EnableAutoConfiguration的数据,然后添加到容器里边。

在这里插入图片描述

4.@Conditional注解

现在SpringBoot自动配置信息有了,自动配置还差什么呢?
到这一步为止,SpringBoot已经为我们的项目中导入了大量的自动配置类,且项目中的自动配置类全部执行,但是这133个自动配置类我们都会用到吗?
以RedisAutoConfiguration为例:
在这里插入图片描述
看到这里就不难发现,虽然SpringBoot帮我们加载了Redis的自动配置类,但并没有把redisTemplate模板类帮我们注入容器,真正想要注入模板类到容器里供我们使用之前,还要经过一些选择注解的判断且全部成功才可以成功注入。
以redisTemplate模板类为例,它想要成功注入,就得经过三个选择注解的全部成功才可以注入:

//项目中必须要有RedisProperties这个类才可以生效(坐标中倒入)
@EnableConfigurationProperties({RedisProperties.class})
//容器中必须没有一个Bean为redisTemplate,这也就允许我们自己向容器中注入一个redisTemplate!
@ConditionalOnMissingBean(name = {"redisTemplate"})//指定必须是单例工厂才能生效
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)

只有在经过这三个选择注解后,自动装配才算真正完成,redisTemplate类才能供我们在项目中使用。


总结

  • @EnableAutoConfiguration 注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置类;
  • 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当 SpringBoot应用启动时,会自动加载这些配置类,初始化Bean;
  • 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean。

相关文章:

源码角度解析SpringBoot 自动配置

文章目录 前言一、了解相关注解1.Condition注解2.Enable注解 二、SpringBoot自动配置1.SpringBootApplication注解2.SpringBootConfiguration注解3.EnableAutoConfiguration注解4.Conditional注解 总结 前言 Spring Boot 自动配置是 Spring Boot 的核心特性之一&#xff0c;它…...

【原创】H3C路由器OSPF测试

网络拓扑图 路由器配置&#xff1a; 路由器1上接了4跟线&#xff0c;分别为这四个接口配置IP地址。 # interface GigabitEthernet0/0/0port link-mode routecombo enable copperip address 2.1.1.2 255.255.255.0 # interface GigabitEthernet0/0/1port link-mode routecombo…...

计算机视觉:轨迹预测综述

计算机视觉&#xff1a;轨迹预测综述 轨迹预测的定义轨迹预测的分类基于物理的方法&#xff08;Physics-based&#xff09;基于机器学习的方法&#xff08;Classic Machine Learning-based&#xff09;基于深度学习的方法&#xff08;Deep Learning-based&#xff09;基于强化学…...

三维跨孔电磁波CT数据可视化框架搭建

三维跨孔电磁波CT数据可视化框架搭建 文章目录 三维跨孔电磁波CT数据可视化框架搭建1、三维CT可视化结果2、matlab代码2.1、CT数据格式整理并保存2.2、三维可视化 利用matlab实现对跨孔电磁波CT实测数据反演&#xff0c;并搭建了三维CT数据可视化框架&#xff0c;可装填实测CT反…...

OC和Swift混编,导入头文件‘xxx-Swift.h‘ file not found

在OC的项目里加入Swift代码&#xff0c;创建完桥接文件后&#xff0c;需要倒入Swift头文件&#xff0c;头文件的格式为“项目名-Swift.h”。 如下图&#xff0c;我在Xcode上看到我的项目名为YichangPark&#xff0c;导入 #import "YiChangPark-Swift.h" 之后提示 “Y…...

一文读懂HOOPS Native平台:快速开发桌面端、移动端3D应用程序!

HOOPS Native Platform是用于在桌面和移动平台以及混合现实应用程序上构建3D工程应用程序的首要工具包。它由三个集成良好的软件开发工具包(SDK)组成&#xff1a;HOOPS Visualize、HOOPS Exchange、HOOPS Publish。HOOPS Visualize 是一个强大的图形引擎&#xff0c;适用于本机…...

Scrum工作模式及Scrum工具

Scrum工作模式是一种敏捷软件开发方法&#xff0c;其核心是团队合作和自我组织&#xff0c;旨在通过短周期的迭代开发&#xff0c;实现快速反馈和持续改进。 Scrum工作模式包括以下角色和活动&#xff1a; 1、产品负责人&#xff08;Product Owner&#xff09;&#xff1a;负…...

[ros][ubuntu]ros在ubuntu18.04上工作空间创建和发布一个话题

构建catkin工作空间 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace cd ~/catkin_ws/ catkin_make 配置环境变量 echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc 检查环境变量 echo $ROS_PACKAGE_PATH…...

我的区块链笔记

区块链 中心化的账本&#xff0c;个人节点和中心节点的地位不对等&#xff0c;中心节点说了算。去中心化&#xff0c;个人节点就是公平的&#xff0c;根据一套规则&#xff0c;叫做公比机制。 区块链的本质&#xff0c;就是数据存储方式 区块链使用密码学算法产生的区块&…...

Spring事务(ACID特性、隔离级别、传播机制、失效场景)

一、事务的ACID特性 原子性&#xff08;Atomicity&#xff09; 原子性是指事务是一个不可分割的工作单位&#xff0c;事务中的操作要么都发生&#xff0c;要么都不发生。一致性&#xff08;Consistency&#xff09; 事务前后数据的完整性必须保持一致。隔离性&#xff08;Isola…...

机器学习笔记之最优化理论与方法(六)无约束优化问题——最优性条件

机器学习笔记之最优化理论与方法——无约束优化问题[最优性条件] 引言无约束优化问题无约束优化问题最优解的定义 无约束优化问题的最优性条件无约束优化问题的充要条件无约束优化问题的必要条件无约束优化问题的充分条件 引言 本节将介绍无约束优化问题&#xff0c;主要介绍无…...

E5061B/是德科技keysight E5061B网络分析仪

181/2461/8938产品概述 是德科技E5061B(安捷伦)网络分析仪在从5 Hz到3 GHz的宽频率范围内提供通用的高性能网络分析。E5061B提供ENA系列常见的出色RF性能&#xff0c;还提供全面的LF(低频)网络测量能力&#xff1b;包括内置1 Mohm输入的增益相位测试端口。E5061B从低频到高频的…...

2.4 PE结构:节表详细解析

节表&#xff08;Section Table&#xff09;是Windows PE/COFF格式的可执行文件中一个非常重要的数据结构&#xff0c;它记录了各个代码段、数据段、资源段、重定向表等在文件中的位置和大小信息&#xff0c;是操作系统加载文件时根据节表来进行各个段的映射和初始化的重要依据…...

Vue2项目练手——通用后台管理项目第五节

Vue2项目练手——通用后台管理项目 首页组件布局面包屑&tag面包屑使用组件使用vuex存储面包屑数据src/store/tab.jssrc/components/CommonAside.vuesrc/components/CommonHeader.vue tag使用组件文件目录CommonTag.vueMain.vuetabs.js 用户管理页新增功能使用的组件页面布局…...

软件工程学术顶会——ESEC/FSE 2022 议题(网络安全方向)清单、摘要与总结

总结 本次会议中网络安全相关议题涵盖区块链、智能合约、符号执行、浏览器API模糊测试等不同研究领域。 热门研究方向: 1. 基于深度学习的漏洞检测与修复 2. 基于AI的自动漏洞修复 3. 模糊测试与漏洞发现 冷门研究方向: 1. 多语言代码的漏洞分析 2. 代码审查中的软件安全 3. 浏…...

从C语言到C++_36(智能指针RAII)auto_ptr+unique_ptr+shared_ptr+weak_ptr

目录 1. 智能指针的引入_内存泄漏 1.1 内存泄漏 1.2 如何避免内存泄漏 2. RAII思想 2.1 RAII解决异常安全问题 2.2 智能指针原理 3. auto_ptr 3.1 auto_ptr模拟代码 4. unique_ptr 4.1 unique_ptr模拟代码 5. shared_ptr 5.1 shared_ptr模拟代码 5.2 循环引用 6.…...

C++信息学奥赛1187:统计字符数

#include <bits/stdc.h> using namespace std; int main() {string arr;cin >> arr; // 输入一个字符串int n, a, max; // 定义变量n, a, maxchar ArrMax; // 定义字符变量ArrMaxn arr.length(); // 获取字符串长度max a 0; // 初始化max和a为0// 外层循环&…...

计算机毕设 大数据商城人流数据分析与可视化 - python 大数据分析

文章目录 0 前言课题背景分析方法与过程初步分析&#xff1a;总体流程&#xff1a;1.数据探索分析2.数据预处理3.构建模型 总结 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到…...

vscode上搭建go开发环境

前言 Go语言介绍&#xff1a; Go语言适合用于开发各种类型的应用程序&#xff0c;包括网络应用、分布式系统、云计算、大数据处理等。由于Go语言具有高效的并发处理能力和内置的网络库&#xff0c;它特别适合构建高并发、高性能的服务器端应用。以下是一些常见的Go语言应用开发…...

10.(Python数模)(预测模型二)LSTM回归网络(1→1)

LSTM回归网络&#xff08;1→1&#xff09; 长短期记忆网络 - 通常只称为“LSTM” - 是一种特殊的RNN&#xff0c;能够学习长期的规律。 它们是由Hochreiter&#xff06;Schmidhuber&#xff08;1997&#xff09;首先提出的&#xff0c;并且在后来的工作中被许多人精炼和推广。…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...