SpringBoot 2.7.4 流程源码概述
1.创建SpringApplication对象
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方法
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)
EventPublishingRunListener的starting方法创建了ApplicationStartingEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共三个支持),并调用listener的onApplication方法(循环启动这些监听器)
2.3 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
封装启动参数到 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
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方法(循环启动这些监听器)
2.4.3.1 EnvironmentPostProcessorApplicationListener
获取getEnvironmentPostProcessors 执行postProcessEnvironment
tips:ConfigFileApplicationListener类2.4后弃用,由ConfigDataEnvironmentPostProcessor
进行替代
this.getConfigDataEnvironment(environment, (ResourceLoader)resourceLoader, additionalProfiles).processAndApply();
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);
给上下文进行赋值
2.7.1 context.setEnvironment(environment);
2.7.2 this.applyInitializers(context);
将7个Initializer 设置到context的facatoryPostProcessor或listener里
2.7.3 listeners.contextPrepared(context);
EventPublishingRunListener的contextPrepared方法创建了ApplicationContextInitializedEvent对象
并通过supportsEvent从所有的listeners过滤(全部为上文springFactory提到的8个),
查看哪些listener支持(共2个支持),但是都是空实现
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个支持)
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个支持)
2.11 this.callRunners(context, applicationArguments);
在项目开发中,经常需要在项目启动的时候去读取配置文件、或者把数据库的数据加载到缓存中。Spring Boot提供了ApplicationRunner和CommandLineRunner来帮助我们实现这些需求,他们都是在Spring容器初始化完毕之后执行起run方法。
ApplicationRunner优先于CommandLineRunner执行,在Order相同的情况下
ApplicationRunner的入参是解析过的,CommandLineRunner的入参没有处理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了