SpringBoot源码分析之-启动流程分析二(run方法步骤介绍)

【SpringBoot】SpringBoot核心启动流程源码解析 阅读详情

前言

上一篇:SpringBoot源码分析之-启动流程分析一(SpringApplication构造器)分析了SpringApplication的构造初始化,初始化主要设置加载类,项目类型(非web,servlet web,响应式web),上下文初始化器,监听器,程序主入口. 还介绍了一些方法的实现.
这篇主要分析run方法做了什么事情

run主要流程介绍

1.创建一个StopWatch,用于监控启动过程
2.设置程序为无显示模式
3.获取监听器SpringApplicationRunListener,用于启动过程的事件广播
4.广播启动事件(ApplicationStartingEvent)
5.环境准备 environment 广播
6.创建上下文
7.获取SpringBootExceptionReporter , (启动失败的异常信息日志)
8.准备上下文
9.刷新上下文
10.刷新上下文之后的一些扩展 (现在是空的,有需要自己可以重写)
11.输出启动的时间
12.广播启动成功事件
13. callRunners 执行自定义的业务代码(比如业务初始化)
13.广播运行成事件
	/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		//创建一个StopWatch,用于监控启动过程
		StopWatch stopWatch = new StopWatch();
		//启动时间戳:纳秒
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//设置了系统全局变量 java.awt.headless, true  
		//用于在缺失显示屏、鼠标或者键盘时的系统配置,也就是Web服务
		configureHeadlessProperty();
		
		//获取监听器SpringApplicationRunListener,用于启动时的事件广播
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//广播ApplicationStartingEvent事件
		listeners.starting();
		try {
			// 参数封装
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 准备环境:命令行参数,系统参数,配置文件,外部配置文件,(非web/web/响应式web)项目环境
            //2、广播ApplicationEnvironmentPreparedEvent事件
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			// 设置系统变量spring.beaninfo.ignore, true
			configureIgnoreBeanInfo(environment);
			//打印banner
			Banner printedBanner = printBanner(environment);
			// 创建ConfigurableApplicationContext 应用上下文容器
			context = createApplicationContext();
			//创建SpringBootExceptionReporter, 启动异常后的相关处理
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//准备容器
			//广播ApplicationEnvironmentPreparedEvent事件
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//刷新上下文
			refreshContext(context);
			//刷新上下文之后的一些扩展,现在是空方法
			afterRefresh(context, applicationArguments);
			//启动完成计算启动耗时
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			//广播容器启动成功
			listeners.started(context);
			//可以执行一些业务初始化  通过ApplicationRunner,CommandLineRunner
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			//广播 容器运行
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

方法介绍

configureHeadlessProperty();

设置请求头

private void configureHeadlessProperty() {
		// private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}

getRunListeners()

//获取EventPublishingRunListener实例

	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}
	
	SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<>(listeners);
	}

通过类路径下所有的 META-INF/spring.factories获取SpringApplicationRunListener的实现类,目前只有一个EventPublishingRunListener

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

SpringApplicationRunListener相关代码分析放在下一篇介绍

createApplicationContext()

根据构建SpringApplication是确定的项目类型, 创建不同上下文

	protected ConfigurableApplicationContext createApplicationContext() {
		Class<?> contextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
				switch (this.webApplicationType) {
				case SERVLET:
					contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
					break;
				case REACTIVE:
					contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
					break;
				default:
					contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
				}
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
			}
		}
		return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
	}

refreshContext(context);

刷新上下文, 就是初始化Spring项目. 具体行为后续博客再分析

afterRefresh(context, applicationArguments);

刷新上下文之后的一些扩展,现在是空方法

callRunners(context, applicationArguments);

业务相关初始化代码可以通过实现ApplicationRunner 或 CommandLineRunner来实现.

private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List<Object> runners = new ArrayList<>();
		//容器里获取ApplicationRunner实现bean
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
		//获取CommandLineRunner
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
		//排序
		AnnotationAwareOrderComparator.sort(runners);
		for (Object runner : new LinkedHashSet<>(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}
	
	private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
		try {
			(runner).run(args);
		}
		catch (Exception ex) {
			throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
		}
	}

	private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
		try {
			(runner).run(args.getSourceArgs());
		}
		catch (Exception ex) {
			throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
		}
	}
SpringBoot运行流程源码分析------阶段二(run方法核心流程) 在上面的代码中,实例化监听器需要有一个默认的构造方法,且构造方法的参数为Class 阅读详情

相关推荐

[Spring Boot] 1. Spring Boot启动过程源码分析

关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Spring-boot 1.5.6)的角度来看看Spring Boot的启动过程到底是怎么样的,为何以往纷繁复杂的配置到如今可以这么简便。1. 入口类package com.example.demo;import org.springframework.boot.SpringApplication; import org

不忘初心,好好沉淀 2万+

SpringBoot启动流程

封装main方法的参数,写入到 Environment中,发布 ApplicationEnvironmentPreparedEvent(环境事件)。(2)创建并初始化监听器SpringApplicationRunListeners,并启动监听,用于监听run方法的执行。(3)创建并初始化ApplicationArguments,获取run方法传递的args参数。(1)创建并初始化计时器StopWatch,用来记录SpringBoot的启动时间。

m0_51431003的博客 3353

Spring Boot 2.2.2 启动过程源码分析.md

Spring Boot 2.2.2 启动过程源码分析,SpringApplication 实例 run 方法运行过程,.分析了 SpringApplication 实例对象构造方法初始化过程,下面继续来看下这个 SpringApplication 对象的 run 方法的源码和运行流程。

springboot run方法执行流程分析

应⽤上下⽂环境包括计算机的环境,Java环境,Spring的运⾏环 境,Spring项⽬的配置(在SpringBoot中就是那个熟悉的 application.properties/yml)等等。在这⾥,获取的是key为 org.springframework.context.ApplicationContextInitializer 的类。⽅法中主要完成的⼯作,⾸先是创建并按照相应的应⽤类型配 置相应的环境,然后根据⽤户的配置,配置系统环境,然后启动监听器,并加载系 统配置⽂件。

m0_62520968的博客 1241

概率论与数理统计基础概念与重要定义汇总

文章目录一、随机事件和概率1:互斥,对立,独立事件的定义和性质。2:概率,条件概率和五大概率公式3:古典型,几何型概率和伯努利试验 一、随机事件和概率 1:互斥,对立,独立事件的定义和性质。 互斥事件\color{red}\textbf{互斥事件}互斥事件 事件A和B的交集为空,A与B就是互斥事件,也叫互不相容事件。也可叙述为:不可能同时发生的事件。如A∩B为不可能事件(A∩B=Φ),那么称事件A与事件B互斥,其含义是:事件A与事件B在任何一次试验中不会同时发生。 则P(A+B)=P(A)+P(B)(这个公

csyifanZhang的博客 1万+

COMSOL模拟CO2驱替CH4:多物理场耦合建模与工程应用详解

在非常规天然气开发与碳封存工程中,多孔介质内的渗流、吸附与岩石变形相互耦合,使得CO2驱替CH4的产能预测和CO2封存评估无法仅靠经验公式完成。以达西定律描述裂隙流动、以扩展Langmuir方程刻画竞争吸附、用应力-吸附-渗透率关系关联煤岩变形,是多物理场耦合数值模拟的核心路径。COMSOL Multiphysics凭借内置渗流、固体力学与组分传递接口,能够将这些机制整合为可参数化扫描的仿真模型,为注气压力、井距、渗透率演化等方案设计提供量化依据。围绕CO2驱替CH4模拟的建模流程、参数取法与结果判读,可形

weixin_29574585的博客 160

springboot启动流程源码解析(带流程图)

版权声明:本文为优快云博主「wuweixianzheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.youkuaiyun.com/zkr1234562/article/details/128053698。

meser88的博客 949

FPS游戏自动枪械识别+压枪(以PUBG为例)

使用Python3.9作为开发环境,实现一个通用的FPS游戏自动检测枪械配件+压枪宏的软件开发思路

weixin_37827742的博客 3万+

Spring Boot-SpringApplication.run方法执行流程详解

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net SpringApplication 是将一个典型的 Spring 应用启动的流程“模板化”,在没有特殊需求的情况下,默认模板化后的执行流程就可以满足需求。但如果有特殊需求也没关系,SpringApplication 在适当的流程结点开放了一系列不同类型的扩展点,我们可以通过这些扩展点对 SpringBoot 程序的启动和关闭过程进行扩展。 最直接的扩展是 S

了解➔熟悉➔掌握➔精通 8953

Python 爬虫实战:爬取评论数据做情感分析

摘要:本文介绍基于Python的京东商品评论爬取与情感分析全流程实现。通过Requests库抓取评论数据接口,结合JSON解析获取结构化评论信息。利用SnowNLP进行中文文本情感分析,量化用户评价的情感倾向(正面/负面/中性)。结果显示正面评论占比66.3%,负面评论13.3%,关键词分析发现"卡顿""发热"是主要负面因素。该方法可应用于产品优化、品牌管理等场景,为决策提供数据支持。

2503_91057718的博客 1709

材料力学数值方法:细观力学模拟:材料断裂与损伤的细观模拟_2024-08-05_16-13-13.Tex

弹性理论是材料力学的一个重要分支,主要研究在外部载荷作用下,材料如何发生弹性变形以及如何恢复原状。这一理论基于连续介质力学,将材料视为由无数连续点组成的连续体,每个点都遵循一定的力学规律。弹性理论的核心是胡克定律,它表明在弹性范围内,应力与应变成正比关系。损伤变量ddd通常定义为0到1之间的值,其中d0d=0d0表示材料未损伤,d1d=1d1表示材料完全损伤。损伤变量可以基于不同的物理量定义,如裂纹密度、孔隙率或微观缺陷的分布。

938

springboot进阶(8):图解Springboot启动流程

文章目录前言springboot启动流程图第一部分 new SpringApplication()第二部分 工厂对象构建实例第三部分 SpringApplication.run(启动此应用)第四部分 SpringApplicationRunListener第五部分 banner彩蛋 前言 研究springboot启动的整个流程。 springboot启动流程图 第一部分 new SpringApplication() 第二部分 工厂对象构建实例 第三部分 SpringApplication.

不积跬步,无以至千里 3602

基于matlab的轴承损伤分析动力学建模仿真

高质量的轴承在正确的使用下,可以使用很长一段时间,如果过早的出现损伤,很可能是因为选型错误,使用不当或润滑不良造成的。因此,在安装轴承时,我们需要记录机器种类,安装部位,使用条件及周围配合。通过研究总结轴承损伤的类型,发生问题时的使用环境,以避免类似情况再次发生。轴承损伤方式按下述图片分类,我们可以图片中显示的主要特征来判断轴承损伤形式。01、压痕碰伤卡入固体异物或冲击造成的表面凹坑及安装是的擦伤◆固体异物侵入◆在倾斜状态下安装◆安装不良造成的撞击,脱落◆卡入剥离片◆改善安装、使用方法。

平时工作较为繁忙,私信消息一般晚上回复,谢谢大家~~ 2667

【二】SpringBoot源码分析之启动主流程----SpringApplication的run方法

一、简介 上一篇说了SpringApplication的创建,这一篇说run方法,关于IOC容器、BeanFactory、ServletContainer的创建和启动、Bean的注册和实例化都在run方法中。 调试源码的时候注意: ApplicationContext为常说的Spring容器、IOC容器、应用上下文、Spring上下文。 ApplicationContext中有BeanFa...

Sid小杰的博客 1173

11、气动外形优化中的连续伴随方法

本文探讨了连续伴随方法在气动外形优化中的理论背景、实现和验证过程。通过使用DLR的FLOWer求解器,将伴随方法应用于Euler和Navier-Stokes方程,以高效计算成本函数梯度,从而显著减少优化过程中的计算成本。文章还介绍了该方法在RAE2822翼型和ONERA M6机翼等案例中的应用,并展示了其准确性和效率。未来展望包括扩展到复杂流动模拟和多学科优化。

desk3的博客 167

springboot启动流程源码分析(二)run(args)

①整个run方法 ②对整个Run方法进行注释说明 /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationConte

JavaTeachers的博客 476

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

SpringBoot 源码分析:启动流程、自动装配

通过对 SpringBoot 启动过程的源码分析,我们了解到从启动入口SpringApplication的构造函数初始化各种组件,到run方法中完成环境准备、上下文创建、Bean 加载和初始化等一系列复杂而有序的操作。 同时,自动配置机制通过spring.factories文件和条件注解,实现了根据依赖自动配置应用的功能。 深入理解这些原理,将帮助我们更好地使用 SpringBoot 开发高效、稳定的应用程序。在实际开发中,如果遇到启动问题或想要定制化启动过程,我们就可以从这些原理出发,快速定位和解决问题。

qq_45464560的博客 926

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

全网最详细的介绍SpringBoot启动过程源码分析

这就是Spring Boot的整个启动流程,其核⼼就是在Spring容器初始化并启动的基础上加⼊各种扩展点,这些扩展点包括: ApplicationContextInitializer、ApplicationListener以及各种BeanFactoryPostProcessor等等。你对整个流程的细节不必太过关注,你只要理解这些扩展点是在何时如何⼯作的,能让它们为你所⽤即可。

码农飞哥 3365

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

springboot启动源码分析2——run方法分析

springboot源码分析

weixin_51929597的博客 519

springboot源码分析-启动流程分析

springboot源码分析-启动流程分析

qq_40748336的博客 1253

Spring Boot启动流程-源码分析

在这个方法中,去spring.factories文件中去加载以 BootstrapRegistryInitializer 全路径名为key的value值,然后调用 createSpringFactoriesInstances 方法通过类名和类加载器将对应的BootstrapRegistryInitializer (也就是spring.factories文件中的value值)实例化,初始化器、监听器的加载调用了同样的方法。不是重点,不做纠结。

weixin_44954504的博客 1157

SpringBoot启动流程分析(二):SpringApplication的run方法

SpringBoot系列文章简介 SpringBoot源码阅读辅助篇:   Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一):SpringApplication类初始化过程 SpringBoot启动流程分析(二):SpringApplication的run方法 SpringBoot启动流程分析(三):S...

weixin_30293079的博客 196

【SpringBoot】一、SpringBoot启动流程源码分析

SpringBoot启动流程源码分析

weixin_43333483的博客 432

01、SpringBoot 源码分析 - SpringApplication启动流程一

之所以能那么强大,扩展性那么好,底层还是依赖spring,他的注解,他的处理器,他的监听器,可以有无数的扩展,废话不多说,当然还是老习惯,这次要分析Spring Boot 2.2.6.RELEASE版本的,要搞懂的原理,得先从他的初始化开始,然后层层深入,各个击破。

深入Java世界:探索编程之美与技术深度 854

springboot项目启动的源码分析,springboot项目run方法底层原理(超详细,必会)

文章目录springboot项目启动的本质,springboot项目run方法底层原理初始化SpringApplicationRun方法深究 springboot项目启动的本质,springboot项目run方法底层原理 今天刚做完核酸闲的无聊还是拔一下源码解解乏 springboot启动首先执行的就是run方法,直接上源码: ——>run——>run 初始化SpringApplication 发现这里初始化了一个SpringApplication,点进去看一下嘛咱们: 重点看下下面两个方

世上哪有什么岁月静好,不过是有人替你负重前行 2638
上一篇: SpringBoot源码分析之-启动流程分析一(SpringApplication构造器)
下一篇: SpringBoot源码分析之-启动流程分析三(监听器SpringApplicationRunListener)
卷心菜~
博客等级 码龄10年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值