大家都知道springboot的启动是通过一个main函数执行一个
SpringApplication.run(*.class, args); 来启动整个项目的。今天我想整理一下SpringApplication.run的启动流程便于自己日后的学习。
本文以spring-boot-starter-parent 2.5.2版本为例分析
1.首先创建一个StopWatch对象用于发布一个开始事件,此类主要是用于统计任务的运行时间的
2.创建 DefaultBootstrapContext实例
private DefaultBootstrapContext createBootstrapContext() { DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();//创建 DefaultBootstrapContext实例 this.bootstrapRegistryInitializers.forEach((initializer) -> //遍历注册表初始化器 initializer.initialize(bootstrapContext));//每个注册表初始器初始化上下文 return bootstrapContext; }
bootstrapRegistryInitializers是通过getBootstrapRegistryInitializersFromSpringFactories()
实质上是通过SpringFactoriesLoader的loadSpringFactories方法遍历整个ClassLoader中所有jar包下的meta-INF包下spring.factories文件的初始化配置。
3.configureHeadlessProperty(); 设置java.awt.headless为true表示运行在服务器器端,在没有显示器器和鼠标键盘的模式下工作,模拟 输入输出设备功能。
4.SpringApplicationRunListeners listeners = getRunListeners(args);//创建所有 Spring 运行监听器并发布应用启动事件(获取spring-boot jar包meta-INF下spring.factories下SpringApplicationRunListener的配置
listeners.starting(bootstrapContext, this.mainApplicationClass);//启动各个SpringApplicationRunListener 监听器实例(EventPublishingRunListener)
5.初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
6.根据运行监听器和应用参数来准备 Spring 环境,springboot2.0当中一共定义了三种环境:none, servlet, reactive
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { // Create and configure the environment //根据应用类型,创建应用环境:如得到系统的参数、JVM及Servlet等参数 ConfigurableEnvironment environment = getOrCreateEnvironment(); //环境属性配置 //加载系统的属性配置来源 configureEnvironment(environment, applicationArguments.getSourceArgs()); //将sources封装成了一个名叫configurationProperties的ConfigurationPropertySourcesPropertySource对象,并把这个对象放到了sources的第一个位置。SpringConfigurationPropertySources是一个将MutablePropertySources转换成ConfigurationPropertySources的适配器 ConfigurationPropertySources.attach(environment); //向监听器发送环境准备事件 listeners.environmentPrepared(bootstrapContext, environment); //将DefaultProperties移动到列表最后 DefaultPropertiesPropertySource.moveToEnd(environment); Assert.state(!environment.containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties."); //将environment中以spring.main开头的source绑定到springApplication中 bindToSpringApplication(environment); //将环境转换为与application能够匹配的类型 if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } //使配置的环境参数与环境匹配 ConfigurationPropertySources.attach(environment); return environment; }
7.设置需要忽略的bean,读取spring.beaninfo.ignore
8.打印启动的banner图,默认为Spring,如需自定义,可修改resources下的banner.txt文件
文字转txt
http://patorjk.com/software/taag/#p=display&h=0&v=1&f=3D%20Diagonal&t=Type%20Something%20
图片转txt
https://www.degraeve.com/img2txt.php
9.创建spring容器
10.准备容器主要是调用所有初始化类的initialize方法,准备上下文的资源
(1)将准备好的environment设置给applicationContext
(2)向beanFactory中添加了一个beanNameGenerator,BeanNameGenerator用来生成扫描到的Bean在容器中的名字
(3)遍历调用所有的ApplicationContextInitializer的initialize()来对已经创建好的ApplicationContext进行进一步的处理
(4)调用SpringApplicationRunListener的contextPrepared()方法,通知所有的监听者,ApplicationContext已经准备完毕
(5)调用SpringApplicationRunListener的contextLoaded()方法,通知所有的监听者,ApplicationContext已经装载完毕
11.完善上下文,加载业务bean,启动tomcat,发布对应事件
12.执行Spring容器的初始化的后置逻辑,默认为空
13.通知SpringApplicationRunListeners的,Spring容器启动完成
14.调用ApplicationRunner或CommandLineRunner的运行方法
15.异常处理
这是本人简单整理的一个springboot启动流程,如有遗漏还请见谅~欢迎指正
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)