SpringBoot自动配置原理、启动流程分析

注:本文总结来自B站尚硅谷SpringBoot2教程
视频:https://www.bilibili.com/video/BV19K4y1L7MT?p=87&spm_id_from=pageDriver
笔记:https://www.yuque.com/atguigu/springboot/tmvr0e

SpringBoot自动配置原理

引导加载自动配置类

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}


    

1、@SpringBootConfiguration

@Configuration。代表当前是一个配置类

2、@ComponentScan

指定扫描哪些,Spring注解;

3、@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
3.1、@AutoConfigurationPackage

自动配置包?指定了默认的包规则

@Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
public @interface AutoConfigurationPackage {}

//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
  • 利用Registrar给容器中导入一系列组件

  • 将指定的一个包下的所有组件导入进来?MainApplication 所在包下

AutoConfigurationPackages.Registrar.class类

在这里插入图片描述

3.2、@Import(AutoConfigurationImportSelector.class)

1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件

2、调用List configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类

3、利用工厂加载 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件

4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

AutoConfigurationImportSelector类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

configurations信息

img

文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\

........................127个之多

spring-boot-autoconfigure-2.2.1.RELEASE.jar包里META-INF/spring.factories
在这里插入图片描述

3.2、按需开启自动配置项

  • 虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration

3.3、修改默认配置

        @Bean
		@ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
		@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
		public MultipartResolver multipartResolver(MultipartResolver resolver) {
            //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
            //SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
			// Detect if the user has created a MultipartResolver but named it incorrectly
			return resolver;
		}
给容器中加入了文件上传解析器;

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

    @Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
    }

总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定

  • 生效的配置类就会给容器中装配很多组件

  • 只要容器中有这些组件,相当于这些功能就有了

  • 定制化配置

  • 用户直接自己@Bean替换底层的组件

  • 用户去看这个组件是获取的配置文件什么值就去修改。

xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties

3.4、最佳实践

SpringBoot启动过程

详情:https://www.yuque.com/atguigu/springboot/tmvr0e#B7hoA

  • 创建 SpringApplication

  • 保存一些信息。

  • 判定当前应用的类型。ClassUtils。Servlet

  • bootstrappers**:初始启动引导器(List):去spring.factories文件中找** org.springframework.boot.Bootstrapper

  • ApplicationContextInitializer;去spring.factories****找 ApplicationContextInitializer

  • List<ApplicationContextInitializer<?>> initializers

  • ApplicationListener ;应用监听器。spring.factories****找 ApplicationListener

  • List<ApplicationListener<?>> listeners

  • 运行 SpringApplication

  • StopWatch

  • 记录应用的启动时间

  • **创建引导上下文(Context环境)**createBootstrapContext()

  • 获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置

  • 让当前应用进入headless模式。java.awt.headless

  • 获取所有 RunListener**(运行监听器)【为了方便所有Listener进行事件感知】**

  • getSpringFactoriesInstances 去spring.factories****找 SpringApplicationRunListener.

  • 遍历 SpringApplicationRunListener 调用 starting 方法;

  • 相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。

  • 保存命令行参数;ApplicationArguments

  • 准备环境 prepareEnvironment();

  • 返回或者创建基础环境信息对象。StandardServletEnvironment

  • 配置环境信息对象。

  • 读取所有的配置源的配置属性值。

  • 绑定环境信息

  • 监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成

  • 创建IOC容器(createApplicationContext())

  • 根据项目类型(Servlet)创建容器,

  • 当前会创建 AnnotationConfigServletWebServerApplicationContext

  • 准备ApplicationContext IOC容器的基本信息 prepareContext()

  • 保存环境信息

  • IOC容器的后置处理流程。

  • 应用初始化器;applyInitializers;

  • 遍历所有的 ApplicationContextInitializer 。调用 initialize.。来对ioc容器进行初始化扩展功能

  • 遍历所有的 listener 调用 contextPrepared。EventPublishRunListenr;通知所有的监听器****contextPrepared

  • 所有的监听器 调用 contextLoaded。通知所有的监听器 contextLoaded;

  • **刷新IOC容器。**refreshContext

  • 创建容器中的所有组件(Spring注解)

  • 容器刷新完成后工作?afterRefresh

  • 所有监听 器 调用 listeners.started(context); 通知所有的监听器 started

  • **调用所有runners;**callRunners()

  • 获取容器中的 ApplicationRunner

  • 获取容器中的 CommandLineRunner

  • 合并所有runner并且按照@Order进行排序

  • 遍历所有的runner。调用 run 方法

  • 如果以上有异常,

  • 调用Listener 的 failed

  • 调用所有监听器的 running 方法 listeners.running(context); 通知所有的监听器 running

  • **running如果有问题。继续通知 failed 。**调用所有 Listener 的 **failed;**通知所有的监听器 failed

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值