SpringBoot 2.7.4 流程源码概述

image

1.创建SpringApplication对象

image

1.1 webApplicationType设置 (SERVLET)

webApplicationType 有三种类型,REACTIVE、SERVLET、NONE

引入 spring-boot-starter-web 包,就是 SERVLET

引入 spring-boot-starter-webflux 包,是 REACTIVE

都没有就是 NONE

1.2 setInitializers设置

通过getSpringFactoriesInstances方法从 META-INF/spring.factories下获取key为
ApplicationContextInitializer的对象并实例化,共7个
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

1.3 setListeners设置

通过getSpringFactoriesInstances方法从 META-INF/spring.factories下获取key为
ApplicationListener的对象并实例化,共8个
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

1.4 mainApplicationClass设置

查找运行堆栈,找到main方法所在的位置

2.执行run方法

image

2.1 getRunListeners

通过getSpringFactoriesInstances方法从 META-INF/spring.factories下获取key为
SpringApplicationRunListener,共1个

org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

2.2 listeners.starting(bootstrapContext, this.mainApplicationClass)

image
image
image
image
image

EventPublishingRunListener的starting方法创建了ApplicationStartingEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共三个支持),并调用listener的onApplication方法(循环启动这些监听器)

2.3 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)

image

封装启动参数到 DefaultApplicationArguments的resource里

2.4 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            EnvironmentConverter environmentConverter = new EnvironmentConverter(this.getClassLoader());
            environment = environmentConverter.convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

2.4.1 configureEnvironment

配置propertieSources 和 profiles

image

2.4.2 ConfigurationPropertySources.attach((Environment)environment);

往PropertySources里添加了configurationProperties

2.4.3 listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);

EventPublishingRunListener的environmentPrepared方法创建了ApplicationEnvironmentPreparedEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共6个支持),并调用listener的onApplication方法(循环启动这些监听器)

image

2.4.3.1 EnvironmentPostProcessorApplicationListener
获取getEnvironmentPostProcessors 执行postProcessEnvironment
tips:ConfigFileApplicationListener类2.4后弃用,由ConfigDataEnvironmentPostProcessor
进行替代
this.getConfigDataEnvironment(environment, (ResourceLoader)resourceLoader, additionalProfiles).processAndApply();

image

2.5 Banner printedBanner = this.printBanner(environment);

自定义Banner ->图片/text
spring.banner.image.location=file:/D:/pic.jpg

2.6 context = this.createApplicationContext();

创建上下文对象 并未赋值
new AnnotationConfigServletWebServerApplicationContext();

2.7 this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

image

给上下文进行赋值


2.7.1 context.setEnvironment(environment);

image

2.7.2 this.applyInitializers(context);

7个Initializer 设置到context的facatoryPostProcessor或listener里

image
image

2.7.3 listeners.contextPrepared(context);

EventPublishingRunListener的contextPrepared方法创建了ApplicationContextInitializedEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共2个支持),但是都是空实现

image

2.7.4 startLog

if (this.logStartupInfo) {
   this.logStartupInfo(context.getParent() == null);
   this.logStartupProfileInfo(context);
}
打印StartupInfo 和 ActiveProfile日志

2.7.5 beanFactory.registerSingleton("springApplicationArguments", applicationArguments);

往 singletonObjects 和 registeredSingletons 增加springApplicationArguments

2.7.6 beanFactory.registerSingleton("springBootBanner", printedBanner);

往 singletonObjects 和 registeredSingletons springBootBanner

2.7.7 this.load(context, sources.toArray(new Object[0])); ***

  source为主程序类,注册主程序类
  this.beanDefinitionMap.put(beanName, beanDefinition);
  this.beanDefinitionNames.add(beanName);

2.7.8 listeners.contextLoaded(context);

EventPublishingRunListener的contextLoaded方法创建了ApplicationPreparedEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共4个支持)

image

2.8 this.refreshContext(context);

Spring流程 详情看 https://www.jianshu.com/p/577906fa2cc2

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
    // 准备,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写 
    prepareRefresh();

    // 这步比较重要(解析),告诉子类去刷新bean工厂,这步完成后配置文件就解析成一个个bean定义,注册到BeanFactory(但是未被初始化,仅将信息写到了beanDefination的map中)
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
    // 设置beanFactory类加载器,添加多个beanPostProcesser
    prepareBeanFactory(beanFactory);
 
    try {
        // 允许子类上下文中对beanFactory做后期处理
        postProcessBeanFactory(beanFactory);
 
        // 调用BeanFactoryPostProcessor各个实现类的方法
        invokeBeanFactoryPostProcessors(beanFactory);
 
        // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
        registerBeanPostProcessors(beanFactory);
 
        //初始化ApplicationContext的MessageSource
        initMessageSource();
 
        //初始化ApplicationContext事件广播器
        initApplicationEventMulticaster();
 
        // 初始化子类特殊bean(钩子方法)
        onRefresh();
 
        // 注册事件监听器
        registerListeners();
 
        // 初始化所有singleton bean  重点!!重点!!
        finishBeanFactoryInitialization(beanFactory);
 
        // 广播事件,ApplicationContext初始化完成
        finishRefresh();
} catch (BeansException ex) {
....................
}

2.9 this.afterRefresh(context, applicationArguments);

空实现 用于扩展

2.10 listeners.started(context, timeTakenToStartup);

EventPublishingRunListener的started方法创建了ApplicationStartedEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共2个支持)

image

2.11 this.callRunners(context, applicationArguments);

在项目开发中,经常需要在项目启动的时候去读取配置文件、或者把数据库的数据加载到缓存中。Spring Boot提供了ApplicationRunner和CommandLineRunner来帮助我们实现这些需求,他们都是在Spring容器初始化完毕之后执行起run方法。

ApplicationRunner优先于CommandLineRunner执行,在Order相同的情况下
ApplicationRunner的入参是解析过的,CommandLineRunner的入参没有处理
posted @   Acaak  阅读(287)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示