springboot启动源码分析

news/2024/10/18 1:37:30/

概述

springboot启动类

package com.ahs.ahsaccount;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class AhsAccountApplication {public static void main(String[] args) {SpringApplication.run(AhsAccountApplication.class, args);}}

run方法

//SpringApplication.class
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}

实例方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null"); 将启动类放入primarySourcesthis.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//根据classpath 下的类,推算当前web应用类型(REACTIVE, servlet)this.webApplicationType = WebApplicationType.deduceFromClasspath();//去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializersetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//去spring.factories 中去获取所有key: org.springframework.context.ApplicationListenersetListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//根据main方法推算出mainApplicationClassthis.mainApplicationClass = deduceMainApplicationClass();}

获取启动类
获取web应用类型
读取了ApplicationContextInitializer ,ApplicationListener
根据main推算出所在的类

run方法

// SpringApplication.javapublic ConfigurableApplicationContext run(String... args) {// 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。StopWatch stopWatch = new StopWatch();//是记录了启动开始时间stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();// 配置 headless 属性configureHeadlessProperty();// 去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器SpringApplicationRunListeners listeners = getRunListeners(args);//发布1.ApplicationStartingEvent事件,在运行开始时发送listeners.starting();try {// 创建  ApplicationArguments 对象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//  加载属性配置。执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties 和外部的属性配置。预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 忽略beaninfo的beanconfigureIgnoreBeanInfo(environment);//   打印Banner 横幅Banner printedBanner = printBanner(environment);//  创建 Spring 容器。 根据webApplicationType创建Spring上下文context = createApplicationContext();//  异常报告器exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//  主要是调用所有初始化类的 initialize 方法,/预初始化spring上下文prepareContext(context, environment, listeners, applicationArguments,printedBanner);//  初始化 Spring 容器。ioc流程refreshContext(context);// 执行 Spring 容器的初始化的后置逻辑。默认实现为空。afterRefresh(context, applicationArguments);// 停止 StopWatch 统计时长stopWatch.stop();// 打印 Spring Boot 启动的时长日志。if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//  通知 SpringApplicationRunListener 的数组,Spring 容器启动完成。listeners.started(context);// 调用 ApplicationRunner 或者 CommandLineRunner 的运行方法。callRunners(context, applicationArguments);} catch (Throwable ex) {// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}//  通知 SpringApplicationRunListener 的数组,Spring 容器运行中。try {listeners.running(context);} catch (Throwable ex) {//  如果发生异常,则进行处理,并抛出 IllegalStateException 异常handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;
}

prepareEnvironment

// SpringApplication.javaprivate ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {// Create and configure the environment//  创建 ConfigurableEnvironment 对象,并进行配置//根据webApplicationType 创建Environment 创建就会读取: java环境变量和系统环境变量ConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());// 通知 SpringApplicationRunListener 的数组,环境变量已经准备完成。//发布了ApplicationEnvironmentPreparedEvent 的监听器 读取了全局配置文件listeners.environmentPrepared(environment);//  绑定 environment 到 SpringApplication 上bindToSpringApplication(environment);//  如果非自定义 environment ,则根据条件转换if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}// 如果有 attach 到 environment 上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中。ConfigurationPropertySources.attach(environment);return environment;
}

prepareContext

// SpringApplication.javaprivate void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// <1> 设置 context 的 environment 属性context.setEnvironment(environment);// <2> 设置 context 的一些属性postProcessApplicationContext(context);// <3> 初始化 ApplicationContextInitializer//拿到之前读取到所有ApplicationContextInitializer的组件, 循环调用initialize方法applyInitializers(context);// <4> 通知 SpringApplicationRunListener 的数组,Spring 容器准备完成。listeners.contextPrepared(context);// <5> 打印日志if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans// <6> 设置 beanFactory 的属性ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// Load the sources// <7> 加载 BeanDefinition 们Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));// <8> 通知 SpringApplicationRunListener 的数组,Spring 容器加载完成。listeners.contextLoaded(context);
}

refreshContext

// SpringApplication.javaprivate void refreshContext(ConfigurableApplicationContext context) {// <1> 开启(刷新)Spring 容器refresh(context);// <2> 注册 ShutdownHook 钩子if (this.registerShutdownHook) {try {context.registerShutdownHook();} catch (AccessControlException ex) {// Not allowed in some environments.}}
}

callRunners

扩展点

// SpringApplication.javaprivate void callRunners(ApplicationContext context, ApplicationArguments args) {// <1> 获得所有 Runner 们List<Object> runners = new ArrayList<>();// <1.1> 获得所有 ApplicationRunner Bean 们runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());// <1.2> 获得所有 CommandLineRunner Bean 们runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());// <1.3> 排序 runnersAnnotationAwareOrderComparator.sort(runners);// <2> 遍历 Runner 数组,执行逻辑for (Object runner : new LinkedHashSet<>(runners)) {if (runner instanceof ApplicationRunner) {callRunner((ApplicationRunner) runner, args);}if (runner instanceof CommandLineRunner) {callRunner((CommandLineRunner) runner, args);}}
}

总结

1、初始化SpringApplication 从spring.factories 读取 listener ApplicationContextInitializer 。
2.运行run方法
3.读取 环境变量 配置信息等
4. 创建springApplication上下文:ServletWebServerApplicationContext
5. . 预初始化上下文
6.调用refresh 加载ioc容器 加载所有的自动配置类
7、创建servlet容器
8.整个流程中会多次调用很多监听器对外进行


http://www.ppmy.cn/news/248559.html

相关文章

计算机无法启动硬盘损坏,电脑硬盘坏了 它显示出 系统资源不够 没法启动

故障现象&#xff1a;电脑在开机的时候(登录桌面之前)&#xff0c;提示“系统资源不够&#xff0c;无法完成API”点击“确定”后&#xff0c;电脑自动重起。甚至连“安全模式”/“最后一次正确配置”也无法进入。故障原因&#xff1a;C盘的剩余空间过小。lsass.exe 系统错误---…

grub4dos初级教程

grub4dos初级教程 - GRUB4DOS、SYSLINUX及其它启动管理软件讨论专区 - 中国DOS联盟论坛 - 中国DOS联盟之联合DOS论坛 http://cndos.fam.cx/forum/viewthread.php?tid28300&fpage1 目录 1 grub4dos初级教程&#xff0d;入门篇 1.1 grub简介 1.2 如何获得grub4dos最新版…

简短的计算机病毒,最简单的电脑病毒

大家知道最简单的电脑病毒是什么吗?下面就让学习啦小编教大家做一个最简单的电脑病毒吧。 最简单的电脑病毒的做法 1.控制面板->文件资源管理器选项->查看->隐藏已知文件夹类型的扩展名,如果前面勾选了就取消勾选,没有勾选就不用管。 2.新建一个文本文档,重命名为…

计算机系统的优化具体操作,从八个方面来探讨计算机操作系统的优化

内容简介:本文主要从硬盘引导、操作系统引导、载入基本操作系统、定义临时目录、定义虚拟内存盘、载入系统服务、载入自定义服务、定义GUI这八个方面来说明针对操作系统的优化。 不管您使用的是Windows也好,Linux也好,或者是Freebsd(为避免语言烦琐,以下如同时指代Linux和F…

计算机慢怎么解决6,电脑运行速度慢怎么回事 电脑运行速度慢的解决方法

通常而言&#xff0c;便携式电脑的打开速度要比台式电脑的打开速度要快上很多。那么台式电脑运行速度慢&#xff0c;一定是因为它出现了小小的问题了。一种是&#xff0c;我们的电脑体内有非常多的灰尘&#xff0c;没有被我们按时清理哦。还有最大的难题&#xff0c;那便是电脑…

专业英语(一) · NIIT教材中文总结系列①

专业英语(一) —— English for Excellence-Primer 文章号&#xff1a;[2023]001 第一章 破冰(交际交流)(Ice-break) 1.1. 介绍和短对话 打招呼 : 正 式: Morning; How do you do; 非正式: Hey,man; Hows it going; 与陌生人对话: 1. 礼貌(Always be polite); 2. 不辱骂他人(Do…

DOS命令图解教程

DOS命令图解教程 DOS 概述及入门 ——DOS简介  现在家用电脑的操作系统大多都是用的 Windows 95&#xff0c;但在1995年Windows 95推出以前&#xff0c;占统治地位的操作系统是DOS(Disk Operation System 磁盘操作系统)。 接触电脑早一点的人想必都听说过DOS的大名&#xf…

内网渗透之MSF框架模块详细作用介绍

目录 Metasploit Framework MSF主机存活探测类 MSF主机端口扫描类 MSF主机服务探测类 MSF主机反弹shell类 MSF主机服务爆破类 MSF攻击模块利用类 MSF数据库提权类 MSF主机Windows权限提升类 MSF横向移动类 MSFPost 后渗透模块类 MSF主机监听类 Metasploit Framewor…