SpringBoot自动装配及run方法原理探究
自动装配
1、pom.xml
spring-boot-dependencies
:核心依赖在父工程中!- 我们在写或者引入一些SpringBoot依赖的时候,不需要指定版本,就因为有这些版本仓库
1.1 其中它主要是依赖一个父工程,作用是管理项目的资源过滤及插件!
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.5</version><relativePath/> <!-- lookup parent from repository -->
</parent>
1.2 点进去,发现还有一个父依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.6.5</version>
</parent>
1.3 这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心
;
1.4 以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
2、启动器 spring-boot-starter
-
依赖
<dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId> </dependency>
-
springboot-boot-starter-xxx
,说白了就是Springboot的启动场景
-
比如
spring-boot-starter-web
,他就会帮我们自动导入web的所有依赖 -
springboot会将所有的功能场景,都变成一个个的启动器
-
我们要使用什么功能,就只需要找到对应的启动器
start
就好了
3、主程序
3.1、默认的主启动类
//@SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {//以为是启动了一个方法,没想到启动了一个服务SpringApplication.run(SpringbootApplication.class, args);}
}
但是一个简单的启动类并不简单我们来分析一下这些注解都干了什么
3.2、注解(@SpringBootApplication)
-
作用:标注在某个类上说明这个类是
SpringBoot的主配置类
-
SpringBoot就应该运行这个类的
main
方法来启动SpringBoot应用; -
进入这个注解:可以看到上面还有很多其他注解!
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class} ), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {// ...... }
@ComponentScan
-
这个注解在Spring中很重要 ,它对应XML配置中的元素。
-
作用:自动扫描并
加载
符合条件的组件或者bean
, 将这个bean定义加载
到IOC容器
中
@SpringBootConfiguration
-
作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;
-
我们继续进去这个注解查看
// 点进去得到下面的 @Component @Configuration public @interface SpringBootConfiguration {}@Component public @interface Configuration {}
-
这里的 @Configuration,说明这是一个spring的配置类 ,配置类就是对应Spring的xml 配置文件;
-
@Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!
@EnableAutoConfiguration
-
开启自动配置功能
- 以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;
@EnableAutoConfiguration
告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
点进注解接续查看:
-
@AutoConfigurationPackage :自动配置包
@Import({Registrar.class}) public @interface AutoConfigurationPackage { }
-
@import :Spring底层注解@import , 给容器中导入一个组件
-
Registrar.class 作用:自动配置包注册,将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;
-
这个分析完了,退到上一步,继续看
-
-
@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;
-
AutoConfigurationImportSelector :自动配置导入选择器,那么它会导入哪些组件的选择器呢?我们点击去这个类看源码:
// 获取所有的配置 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
-
获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// 和下面的方法对应//这里的getSpringFactoriesLoaderFactoryClass()方法//返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfigurationList<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; } //和上面的类的方法loadFactoryNames里面的第一个参数对应 //这里的getSpringFactoriesLoaderFactoryClass()方法 //返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class; }
-
这个方法
getCandidateConfigurations()
又调用了SpringFactoriesLoader
类的静态方法!我们进入SpringFactoriesLoader
类loadFactoryNames() 方法,获取所有的加载配置public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName();//这里它又调用了 loadSpringFactories 方法return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
-
我们继续点击查看 loadSpringFactories 方法
- 项目资源:
META-INF/spring.factories
- 系统资源:
META-INF/spring.factories
- 从这些资源中配置了所有的nextElement(自动配置),分装成properties
//将所有的资源加载到配置类中(将下面的抽离出来分析,第15行) Properties properties = PropertiesLoaderUtils.loadProperties(resource);
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {//获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {//去获取一个资源 "META-INF/spring.factories"Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");LinkedMultiValueMap result = new LinkedMultiValueMap();//判断有没有更多的元素,将读取到的资源循环遍历,封装成为一个Propertieswhile(urls.hasMoreElements()) {URL url = (URL)urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Entry<?, ?> entry = (Entry)var6.next();String factoryClassName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryName = var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}} }
- 项目资源:
-
发现一个多次出现的文件:
spring.factories
,全局搜索它
-
3.3、spring.factories
我们根据源头打开
spring.factories
, 看到了很多自动配置的文件;这就是自动配置根源所在!
WebMvcAutoConfiguration
我们在上面的自动配置类随便找一个打开看看,比如 :WebMvcAutoConfiguration
可以看到这些一个个的都是JavaConfig配置类,而且都注入了一些Bean,可以找一些自己认识的类,看着熟悉一下!
所以,自动配置真正实现是从classpath中搜寻所有的
META-INF/spring.factories
配置文件 ,并将其中对应的org.springframework.boot.autoconfigure
. 包下的配置项,通过反射实例化为对应标注了@Configuration的JavaConfig
形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。
4、结论:
- SpringBoot在启动的时候从类路径下的
META-INF/spring.factories
中获取EnableAutoConfiguration
指定的值 - 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
- 以前我们需要自动配置的东西,现在springboot帮我们做了
- 整合JavaEE,整体解决方案和自动配置的东西都在
springboot-autoconfigure
的jar包中; - 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器中
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并自动配置,@Configuration(javaConfig) ;
- 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;
启动
1、不简单的方法
我最初以为就是运行了一个
main
方法,没想到却开启了一个服务;
@SpringBootApplication
public class Springboot01HellowordApplication {public static void main(String[] args) {//该方法返回一个ConfigurableApplicationContext对象//参数一:应用入口的类; 参数二:命令行参数 SpringApplication.run(Springboot01HellowordApplication.class, args);}}
SpringApplication.run分析
- 分析该方法主要分两部分
- 一是SpringApplication的实例化,
- 二是run方法的执行;
2、SpringApplication
这个类主要做了以下四件事情:
-
推断应用的类型是普通的项目还是Web项目
-
- 查找并加载所有可用初始化器 , 设置到
initializers
属性中
- 查找并加载所有可用初始化器 , 设置到
-
- 找出所有的应用程序
监听器
,设置到listeners
属性中
- 找出所有的应用程序
-
- 推断并设置main方法的定义类,找到运行的
主类
- 推断并设置main方法的定义类,找到运行的
查看构造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {// ......this.webApplicationType = WebApplicationType.deduceFromClasspath();this.setInitializers(this.getSpringFactoriesInstances();this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = this.deduceMainApplicationClass();
}
3、run方法流程分析
跟着源码和这幅图就可以一探究竟了!
相关文章:
SpringBoot自动装配及run方法原理探究
自动装配 1、pom.xml spring-boot-dependencies:核心依赖在父工程中!我们在写或者引入一些SpringBoot依赖的时候,不需要指定版本,就因为有这些版本仓库 1.1 其中它主要是依赖一个父工程,作用是管理项目的资源过滤及…...

Mybatis实现JsonObject对象与JSON之间交互
项目中使用PostGresql数据库进行数据存储,表中某字段为Json类型,用于存储Json格式数据。PG数据库能够直接存储Json算是一大特色,很多特定情境下使用直接存储Json字段数据能够大量节省开发时间,提高后台数据查询和转换效率。 1、基…...

spring boot 集成 jetcache【基础篇:@Cached、@CreateCache、@CacheRefresh】
手打不易,如果转摘,请注明出处! 注明原文:https://zhangxiaofan.blog.csdn.net/article/details/129832925 目录 前言 版本 配置通用说明 项目结构 代码 启动类 实体类 基础使用——增删改查(Cached、CacheInv…...
个人对前后端分离的一些看法
内容简介:前端开发过程中能完全不依赖后端的才是真正的前后端分离指的是工作过程中,前端的的代码中往往会掺杂一些后端的逻辑。后端返回了一个json对象 前端开发过程中能完全不依赖后端的才是真正的前后端分离 指的是工作过程中,前端的的代码…...
TailWindCss 在Hbuilderx中使用
基于这个插件 weapp-tailwindcss 地址 本次说明基于HbuilderX 创建的项目非CLI 安装步骤按照文档走,先安装上几个依赖。然后是几个配置文件 tailwind-input.css tailwind的css文件用来引入到app.vue /* #ifdef H5 */ tailwind base; /* 如果是小程序的话&#x…...

Unity导入图片时,通过设置属性快速实现资源的压缩
是在学习tilemap绘制世界地图的时候发现的这个功能。 之前一直只是粗略的知道这部分是对应图片资源的压缩的。比如Compression是指的压缩质量,想要完全不压缩就设置None,会导致图片资源会大一些。 在我的例子工程中,其他图片资源的尺寸都是6…...

AlmaLinux 9 安装 Go 1.20
AlmaLinux 9 安装 Golang 1.20 1. 下载 go 安装包2. 安装 go3. 配置环境变量4. 确认 go 版本 1. 下载 go 安装包 访问 https://go.dev/dl/,下载你想安装的版本,比如 go1.20.7.linux-amd64.tar.gz, 2. 安装 go (可选)删除旧版本,…...

【Docker】数据库动态授权组件在Kubernetes集群下的测试过程记录
目录 背景 组件原理 测试设计 环境 测试脚本 脚本build为linux可执行文件 镜像构建 Dockerfile Docker build 镜像有效性验证 总结 资料获取方法 背景 我们都知道出于安全性考虑,生产环境的权限一般都是要做最小化控制,尤其是数据库的操作授…...

数据结构【第3章】——线性表
线性表的定义 线性表:零个或多个数据元素的有限序列。 1)线性表是一个序列。即元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。 2&a…...

MySql之分库分表
数据库瓶颈 不管是IO瓶颈还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载的活跃连接数的阈值。在业务service来看, 就是可用数据库连接少甚至无连接可用,接下来就可以想象了(并发量、吞…...

数据结构—图的遍历
6.3图的遍历 遍历定义: 从已给的连通图中某一顶点出发,沿着一些边访问遍历图中所有的顶点,且使每个顶点仅被访问一次,就叫作图的遍历,它是图的基本运算。 遍历实质:找每个顶点的邻接点的过程。 图的…...
MySQL主从复制基于二进制日志的高可用架构指南
前言 在现代数据库架构中,MySQL主从复制技术扮演着重要角色。它不仅可以提升数据库性能和可扩展性,还赋予系统卓越的高可用性和灾难恢复能力。本文将深入剖析MySQL主从复制的内部机制,同时通过一个实际案例,展示其在实际场景中的…...
RestTemplate HTTPS请求忽略SSL证书
问题描述 使用RestTemplate发送HTTPS请求的时候,出现了这样的一个问题: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification …...

Jenkins触发器时间、次数设定
触发器触发条件介绍 触发器触发条件公式:由5颗星组成 * * * * * 分别代表:分钟(0-59) 小时(0-23) 日期(1-31) 月份(1-12) 星期(0-6) 企业项目中常用场景介绍 场景1:接口脚本部分测试通过,部分还在进行,回归测试脚本执行…...

kafka partition的数据文件(offffset,MessageSize,data)
partition中的每条Message包含了以下三个属性: offset,MessageSize,data,其中offset表示Message在这个partition中的偏移量,offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值&…...
htnl根据轮播图图片切换背景色
htnl根据轮播图图片切换背景色 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>轮播图示例</title><link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/swiper10/swiper-bundle.min.css&q…...

gpu-manager安装及测试
提示:GPU-manager安装为主部分内容做了升级开箱即用,有用请点收藏❤抱拳 文章目录 前言一、约束条件二、使用步骤1.下载镜像1.1 查看当前虚拟机的驱动类型: 2.部署gpu-manager3.部署gpu-admission4.修改kube-scheduler.yaml
Zookeeper特性与节点数据类型详解
CAP&Base理论 CAP理论 cap理论是指对于一个分布式计算系统来说,不可能满足以下三点: 一致性 : 在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的 特性,等同于所有节点访问同一份最新的数据副本。在一致性的需…...

函数的递归
1、什么是递归? 程序调用自身的编程技巧称为递归。 递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解&#x…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...