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

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 , 看到了很多自动配置的文件;这就是自动配置根源所在!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZLr3WvtB-1691558634854)(SpringBoot02:运行原理初探.assets/1595415587435.png)]

WebMvcAutoConfiguration

我们在上面的自动配置类随便找一个打开看看,比如 :WebMvcAutoConfiguration

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4GyCVmvP-1691558634855)(SpringBoot02:运行原理初探.assets/1595416894611.png)]

可以看到这些一个个的都是JavaConfig配置类,而且都注入了一些Bean,可以找一些自己认识的类,看着熟悉一下!

所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。

4、结论:

  1. SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
  2. 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
  3. 以前我们需要自动配置的东西,现在springboot帮我们做了
  4. 整合JavaEE,整体解决方案和自动配置的东西都在springboot-autoconfigure的jar包中;
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器中
  6. 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并自动配置,@Configuration(javaConfig) ;
  7. 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

在这里插入图片描述

启动

1、不简单的方法

我最初以为就是运行了一个main方法,没想到却开启了一个服务;

@SpringBootApplication
public class Springboot01HellowordApplication {public static void main(String[] args) {//该方法返回一个ConfigurableApplicationContext对象//参数一:应用入口的类; 参数二:命令行参数  SpringApplication.run(Springboot01HellowordApplication.class, args);}}

SpringApplication.run分析

  • 分析该方法主要分两部分
  • 一是SpringApplication的实例化,
  • 二是run方法的执行;

2、SpringApplication

这个类主要做了以下四件事情:

    1. 推断应用的类型是普通的项目还是Web项目
    1. 查找并加载所有可用初始化器 , 设置到initializers属性中
    1. 找出所有的应用程序监听器,设置到listeners属性中
    1. 推断并设置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方法流程分析

img

跟着源码和这幅图就可以一探究竟了!

相关文章:

SpringBoot自动装配及run方法原理探究

自动装配 1、pom.xml spring-boot-dependencies&#xff1a;核心依赖在父工程中&#xff01;我们在写或者引入一些SpringBoot依赖的时候&#xff0c;不需要指定版本&#xff0c;就因为有这些版本仓库 1.1 其中它主要是依赖一个父工程&#xff0c;作用是管理项目的资源过滤及…...

Mybatis实现JsonObject对象与JSON之间交互

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

spring boot 集成 jetcache【基础篇:@Cached、@CreateCache、@CacheRefresh】

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/129832925 目录 前言 版本 配置通用说明 项目结构 代码 启动类 实体类 基础使用——增删改查&#xff08;Cached、CacheInv…...

个人对前后端分离的一些看法

内容简介&#xff1a;前端开发过程中能完全不依赖后端的才是真正的前后端分离指的是工作过程中&#xff0c;前端的的代码中往往会掺杂一些后端的逻辑。后端返回了一个json对象 前端开发过程中能完全不依赖后端的才是真正的前后端分离 指的是工作过程中&#xff0c;前端的的代码…...

TailWindCss 在Hbuilderx中使用

基于这个插件 weapp-tailwindcss 地址 本次说明基于HbuilderX 创建的项目非CLI 安装步骤按照文档走&#xff0c;先安装上几个依赖。然后是几个配置文件 tailwind-input.css tailwind的css文件用来引入到app.vue /* #ifdef H5 */ tailwind base; /* 如果是小程序的话&#x…...

Unity导入图片时,通过设置属性快速实现资源的压缩

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

AlmaLinux 9 安装 Go 1.20

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

【Docker】数据库动态授权组件在Kubernetes集群下的测试过程记录

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

数据结构【第3章】——线性表

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 1&#xff09;线性表是一个序列。即元素之间是有顺序的&#xff0c;若元素存在多个&#xff0c;则第一个元素无前驱&#xff0c;最后一个元素无后继&#xff0c;其他每个元素都有且只有一个前驱和后继。 2&a…...

MySql之分库分表

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

数据结构—图的遍历

6.3图的遍历 遍历定义&#xff1a; ​ 从已给的连通图中某一顶点出发&#xff0c;沿着一些边访问遍历图中所有的顶点&#xff0c;且使每个顶点仅被访问一次&#xff0c;就叫作图的遍历&#xff0c;它是图的基本运算。 遍历实质&#xff1a;找每个顶点的邻接点的过程。 图的…...

MySQL主从复制基于二进制日志的高可用架构指南

前言 在现代数据库架构中&#xff0c;MySQL主从复制技术扮演着重要角色。它不仅可以提升数据库性能和可扩展性&#xff0c;还赋予系统卓越的高可用性和灾难恢复能力。本文将深入剖析MySQL主从复制的内部机制&#xff0c;同时通过一个实际案例&#xff0c;展示其在实际场景中的…...

RestTemplate HTTPS请求忽略SSL证书

问题描述 使用RestTemplate发送HTTPS请求的时候&#xff0c;出现了这样的一个问题&#xff1a; sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification …...

Jenkins触发器时间、次数设定

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

kafka partition的数据文件(offffset,MessageSize,data)

partition中的每条Message包含了以下三个属性&#xff1a; offset&#xff0c;MessageSize&#xff0c;data&#xff0c;其中offset表示Message在这个partition中的偏移量&#xff0c;offset不是该Message在partition数据文件中的实际存储位置&#xff0c;而是逻辑上一个值&…...

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安装及测试

提示&#xff1a;GPU-manager安装为主部分内容做了升级开箱即用&#xff0c;有用请点收藏❤抱拳 文章目录 前言一、约束条件二、使用步骤1.下载镜像1.1 查看当前虚拟机的驱动类型&#xff1a; 2.部署gpu-manager3.部署gpu-admission4.修改kube-scheduler.yaml![在这里插入图片描…...

Go和Java实现享元模式

Go和Java实现享元模式 下面通过一个实例来说明享元模式的使用。 1、享元模式 享元模式主要用于减少创建对象的数量&#xff0c;以减少内存占用和提高性能。这种类型的设计模式属于结构型模式&#xff0c;它提 供了减少对象数量从而改善应用所需的对象结构的方式。 享元模式…...

Zookeeper特性与节点数据类型详解

CAP&Base理论 CAP理论 cap理论是指对于一个分布式计算系统来说&#xff0c;不可能满足以下三点: 一致性 &#xff1a; 在分布式环境中&#xff0c;一致性是指数据在多个副本之间是否能够保持一致的 特性&#xff0c;等同于所有节点访问同一份最新的数据副本。在一致性的需…...

函数的递归

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

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

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

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

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...