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

[4-06-09].第10节:自动配置- 分析@SpringBootApplication启动类

SpringBoot学习大纲


一、启动类加载器@SpringBootApplication:

1.1.@SpringBootApplication注解源码:

  • 1.@SpringBootApplication注解是引导加载自动配置类
  • 2.@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan()
    在这里插入图片描述
  • 3.下面依次介绍@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan()这3个注解

1.2.注解1:分析@SpringBootConfiguration注解

  • 1.根据@SpringBootConfiguration注解的源码可以看到,在源码中有注解@Configuration,出现了@Configuration,就代表当前类是一个配置类
  • 2.也就是说在SpringBoot项目中mainApplication这个程序也是SpringBoot中的一个配置类
    在这里插入图片描述

1.3.注解2:分析@ComponentScan注解:

  • 1.@ComponentScan代表的就是包扫描
    在这里插入图片描述
  • 2.@ComponentScan("com.jianqun"):可以设置包扫描路径
  • 3.如果有多个包,就可以写成数组的形式,如@SpringBootApplication(scanBasePackages = {"com.jianqun",“xx.cc.ddd”)}或者也可以使用@ComponentScan ()指定扫描路径

1.4.注解3:分析@EnableAutoConfiguration注解:

a.功能:

  • 1.@EnableAutoConfiguration注解是用于开启自动配置的核心,有了这个注解,就可以使得 spring-boot-autoconfigure下官方写好的所有配置类生效

b.源码

  • 1.在@EnableAutoConfiguration注解的源码中可看到:@EnableAutoConfiguration = @AutoConfigurationPackage + @Import()
    在这里插入图片描述

  • 2.下面的内容分别来分析 @AutoConfigurationPackage和@Import()注解在自动配置中的原理


c.分析 @EnableAutoConfiguration --> @AutoConfigurationPackage:


注解 @AutoConfigurationPackage的 源码

  • 1.功能:@AutoConfigurationPackage 就是自动配置包,它用于指定默认的包规则
    在这里插入图片描述
  • 2.在@AutoConfigurationPackage 注解的源码中又包括了@import注解
    在这里插入图片描述
  • 3.通过源码,可以看到使用@import注解给容器导入了名称是AutoConfigurationPackages.Registar组件,那AutoConfigurationPackages.Registar是什么???就需要分析AutoConfigurationPackages.Registar源码了

AutoConfigurationPackages.Registrar源码分析:

  • 1.通过下图中的Registrar源码可以看到包含了两个方法,分别是registerBeanDefinitions()方法determineImports()方法
    在这里插入图片描述
  • 2.方法1分析:对于registerBeanDefinitions(参数1,参数2)方法,它传递了两个参数;
    在这里插入图片描述
    • 对于参数1: AnnotationMetadata metadata,第一个参数意思是传递的是注解的元信息
      • 这里所指的注解是:@AutoConfigurationPackage,代表的就是这个注解标在哪个位置,都有哪些属性的元信息;
      • 这个注解是标在了MainApplication这个类位置上; 当元信息拿来后,用new PackageImports(metadata).getPackageNames()获取到包名称,然后toArray(new String[0])转封装成数组
        在这里插入图片描述
      • 最后register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]))代码的意思就是 把某MainApplication这个包里面的所有组件批量注册到容器中
        在这里插入图片描述

总结: @AutoConfigurationPackage作用:

  • 作用1是:指定了默认包规则
  • 作用2是:把默认包路径下的所有组件注册到容器中,即把 启动类MainApplication这个包里面的所有组件批量注册到容器中了

d.分析 @EnableAutoConfiguration --> @Import(AutoConfigurationImportSelector.class)


@Import(AutoConfigurationImportSelector.class)作用

  • 1.这里的@Import(AutoConfigurationImportSelector.class)注解是批量导入组件的作用,可以使用程序来定义导入的一堆组件,把这些类的全类名加载进来,最终实现组件的批量导入
    在这里插入图片描述
  • 2.具体是怎么批量导入这些组件的????就需要分析AutoConfigurationImportSelector的源码了,看看具体是怎么把全类名加载进来实现组件批量导入

定位AutoConfigurationImportSelector的源码

  • 1.下图为AutoConfigurationImportSelector类的源码
    在这里插入图片描述
  • 2.在AutoConfigurationImportSelector类的源码中可以看到:主要包括了selectImports(AnnotationMetadata annotationMetadata)等方法
    在这里插入图片描述

分析selectImports(AnnotationMetadata annotationMetadata)方法源码

  • 1.从selectImports(AnnotationMetadata annotationMetadata)方法的源码中,可以看到返回值是一个字符串数组类型的。在这个返回的数组中存储的就是那些需要导入到容器中那一堆组件
    在这里插入图片描述
  • 2.那返回的数组中存储的那一堆组件是怎么来的呢??那就需要分析源码中的getAutoConfigurationEntry(annotationMetadata)方法了!!
    在这里插入图片描述

分析selectImports(参数) 方法中的getAutoConfigurationEntry(annotationMetadata)方法源码

  • 1.如下是getAutoConfigurationEntry(annotationMetadata)方法的源码:
    在这里插入图片描述
  • 2.在源码中可以看到:List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes),通过调用 getCandidateConfigurations()方法用于获取到那些需要导入到容器中的那一堆组件
    在这里插入图片描述
  • 3.如下debugger中可以看出configurations变量一共存储的131个组件,这131个组件就是需要导入容器中的
    在这里插入图片描述

分析getCandidateConfiguration()源码:

  • 1.点击getCandidateConfiguration() 方法,进入方法内部:
    在这里插入图片描述
  • getCandidateConfiguration()方法在SpringBoot2和SpringBoot3中的实现方式有了变化!!!!下面对此分别进行分析

============== 分析getCandidateConfiguration()方法在SpringBoot2中的实现 ------------ 开始 ==============

  • 1、getCandidateConfiguration() 方法源码
    • getCandidateConfiguration() 方法中利用了Spring的工厂加载器SpringFactoriesLoader.loadFactoryNames()又加载了一些东西,加载的这些就是上面List中存储的那131个组件
      在这里插入图片描述
    • 2.具体这些组件loadFactoryNames()方法时怎么加载来的就需要分析SpringFactoriesLoader.loadFactoryNames()方法的源码了
  • 2、SpringFactoriesLoader.loadFactoryNames()方法的源码
    • 如下是loadFactoryNames()方法的源码:
      在这里插入图片描述
    • SpringFactoriesLoader.loadFactoryNames()这个方法中的源码中可以看到,通过调用了loadSpringFactories()方法来获取这一堆要加载的组件
      在这里插入图片描述
    • 那loadSpringFactories()方法具体具体是从哪里得到的这一堆要注入容器的组件呢???? 那就要具体分析loadSpringFactories()方法的源码了
  • 3、loadSpringFactories()源码分析:
    • 通过源码分析,可以看到通过loadSpringFactories()方法,得到所有要加载的组件,返回值是Map<String, List<String>>类型的
      在这里插入图片描述
    • 可以从源码中看到lassLoader.getResources()方法会从META-INF/spring.factories位置来加载一个文件,默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
      在这里插入图片描述
    • 比较核心的jar包,即spring-boot-autoconfigure-2.5.2.RELEASE.jar包,在它的里面也有META-INF/spring.factories
      在这里插入图片描述
    • 最终可以看出,在配置文件spring.factories中写死了spring-boot一启动就要给容器中加载的所有配置类xxxxAutoConfiguration
    • 虽然所有的自动配置类在springboot启动的时候都加载了,但还是按照条件配置规则(@ConditionalOnxxx)来进行启动,只有条件成立,才能生效,最终实现了按需配置

============== 分析getCandidateConfiguration()方法在SpringBoot2中的实现 ------------ 结束 ==============


============== 分析getCandidateConfiguration()方法在SpringBoot3中的实现 ------------ 开始 ==============

  • 1、getCandidateConfiguration()方法源码:
    • getCandidateConfiguration() 方法中利用ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())又加载了一些东西,这些就是List中存储的那一堆药加载的组件
    • 这一堆要加载的组件具体是怎么加载进来的,就要分析ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())源码了
      在这里插入图片描述
  • 2、ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())源码
    • 在load()方法的源码中,代码annotation.getName()是获取到注解的全类名,然后在META-INF/spring/%s.imports中,对%s进行替换
      在这里插入图片描述
    • 在这里,annotation.getName()的值是:org.springframework.boot.autoconfigure,对s%进行替换后是:META-INF/spring/org.springframework.boot.autoconfigure.imports,也就是说SpringBoot在底层就会加载导入META-INF/spring/org.springframework.boot.autoconfigure.imports定义的所有类,一共有142个,这就实现了组件的批量导入
      在这里插入图片描述
      ============== 分析getCandidateConfiguration()方法在SpringBoot3中的实现 ------------ 结束 ==============

总结:

  • 1.对于SpringBoot2版本的项目在启动的时候,利用注解@Import(AutoConfigurationImportSelector.class)在底层实际上是从位置为 META-INF/spring.factories位置批量导入一堆组件
  • 2.对于SpringBoot3版本的项目在启动的时候,利用注解@Import(AutoConfigurationImportSelector.class)在底层实际上是从位置为 META-INF/spring/org.springframework.boot.xxxx.imports 中导入一堆组件
  • 3.不论是SpringBoot2还是SpringBoot3每个自动配置类按照条件进行生效

二、自动配置流程:

2.1.定位xxxxAutoConfiguration位置:

  • 1.引入开发所需要的场景启动器后,就会导入相关场景的所有依赖 -> 每个场景启动器都引入了一个spring-boot-starter,这个是核心场景启动器 -> 核心场景启动器引入了spring-boot-autoconfigure包
    在这里插入图片描述
  • 2.spring-boot-autoconfigure里面包含了所有场景的所有配置
    在这里插入图片描述
  • 3.在所有场景的配置中,都有xxxxAutoConfiguration自动配置类:
    在这里插入图片描述

2.2.总结:

  • SpringBoot先加载所有的自动配置类
  • 每个自动配置类都是按照条件进行生效的
  • 生效的配置类就会给容器中装配很多个组件
  • 只要容器中有这些组件,就相当于这些功能就具有了

三、属性绑定:

3.1.分析@EnableConfigurationProperties(ServerProperties.class):

  • 1.每个自动配置类都可能有注解@EnableConfigurationProperties(ServerProperties.class),用来把配置文件中配的指定前缀的属性值封装到 xxxProperties属性类中
  • 2.在容器中使用@Bean放一堆组件

3.2.举例:

  • 1.以Tomcat为例:把服务器的所有配置都是以server开头的,配置都封装到了属性类中
    在这里插入图片描述
    在这里插入图片描述
  • 2.给容器中放的所有组件的一些核心参数,都来自于xxxProperties。xxxProperties都是和配置文件绑定,只需要改配置文件的值,核心组件的底层参数都能修改

四、自定义类绑定配置提示:

4.1.自定义类:

在这里插入图片描述


4.2.配置绑定:

a.问题描述:

  • 我们在配置文件与自定义类绑定到额时候,没有任何提示,不是很友好,我们需要引入依赖进行解决

b.引入依赖:

在这里插入图片描述

c.测试:

在这里插入图片描述


五、总结SpringBoot开发时的核心流程:

  • 1.导入starter,就会导入autoconfigure包
  • 2.autoconfigure 包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定的所有启动要加载的自动配置类
  • 3.@EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来
  • 4.然后xxxAutoConfiguration 回按照条件注解进行按需加载
  • 5.xxxAutoConfiguration给容器中导入一堆组件,组件都是从 xxxProperties中提取属性值,xxxProperties又是和配置文件进行了绑定
    在这里插入图片描述

相关文章:

  • 防爆风扇储能轴流风机风量风压如何保障通风安全?
  • java每日精进 4.29【框架之自动记录日志并插入如数据库流程分析】
  • Lucene 分词工具全解析与对比指南
  • Spring AI在大模型领域的趋势场景题深度解析
  • 网络原理 - 11(HTTP/HTTPS - 2 - 请求)
  • Shopify网上商店GraphQL Admin接口查询实战
  • idm 禁止自动更新提示(修改注册表)
  • Spring MVC中自定义日期类型格式转换器
  • 精益数据分析(32/126):电商指标优化与搜索策略解析
  • 【Python笔记 05】 if判断、比较运算符与逻辑运算符
  • Linux Ollama离线安装/更新教程-适用于国内快速下载Ollama最新版本(亲测好用)--适用于Qwen3 系列模型
  • 2025年- H12-Lc119-56.合并区间(普通数组)---java版
  • ROS2 学习
  • Uniapp:置顶
  • UDP数据报和TCP流套接字编程
  • 【网络原理】TCP异常处理(一):粘包问题
  • WSL2下Docker desktop的Cadvisor容器监控
  • 海思SD3403边缘计算AI核心设备概述
  • AI 边缘计算网关十大品牌
  • 高防CDN如何兼顾防护以及加速
  • 年轻人的事业!6家上海人工智能企业畅想“模范生”新征程
  • 量子传感新技术“攻克”退相干难题
  • 韩国下届大选执政党初选4进2结果揭晓,金文洙、韩东勋胜出
  • 王毅:妥协退缩只会让霸凌者得寸进尺
  • 众信旅游:去年盈利1.06亿元,同比增长228.18%
  • 杭州6宗涉宅用地收金125.76亿元,萧山区地块楼面价冲破5万元/平米