Spring Boot————Spring Boot启动流程分析

一、引言

Spring Boot 的启动虽然仅仅是执行了一个main方法,但实际上,运行流程还是比较复杂的,其中包含几个非常重要的事件回调机制。在实际生产开发中,有时候也会利用这些启动流程中的回调机制,做一些项目初始化的工作,比如内存初始化等。所以,学习Spring Boot启动流程非常重要。

二、启动流程概述

SpringApplication.run(Object, String...)方法的执行中包括以下一些关键步骤:

1、准备环境: 

  1. 执行ApplicationContextInitializer.initialize()
  2. 监听器SpringApplicationRunListener回调contextPrepared()
  3. 加载主配置类(启动类)定义信息
  4. 监听器SpringApplicationRunListener回调contextLoaded()

2、刷新启动IOC容器: 

  1. 扫描加载所有容器中的组件
  2. 从META-INF/spring.factories中获取所有的EnableAutoConfiguration组件

3、回调容器中所有的 ApplicationRunner 、CommandLineRunner 的 run() 方法

4、监听器 SpringApplicationRunListener 回调 finished()方法

三、详细流程剖析

Spring Boot的启动方法调用流程为两步:1、创建SpringApplication对象;2、执行run()方法

这句代码是一个中间的调用过程,接下来,我们将深度讲解创建SpringApplication对象和执行run()方法具体都做了哪些工作。 

1、创建SpringApplication对象

通过SpringApplication的构造器,调用initialize()方法,对SpringApplication中的一些属性初始化默认值,同时,从META-INF/spring.factories找到所有ApplicationContextInitializer和ApplicationListener保存起来。

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {// 保存主配置类if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));}// 判断当前应用是否为一个WEB应用this.webEnvironment = deduceWebEnvironment();// 从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer,然后保存起来setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 从类路径下找到META-INF/spring.factories配置的所有ApplicationListenersetListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 从多个主配置类中找到有main方法的主配置类this.mainApplicationClass = deduceMainApplicationClass();
}

2、运行run(String...)方法

主要做了两件事:

  • 回调:ApplicationContextInitializer和SpringApplicationRunListener;
  • 回调:ApplicationRunner和CommandLineRunner。

详细流程注释如下:

/*** 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 = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;FailureAnalyzers analyzers = null;configureHeadlessProperty();// 获取SpringApplicationRunListeners,从类路径下META-INF/spring-factoriesSpringApplicationRunListeners listeners = getRunListeners(args);// 循环所有的listener,回调starting()方法listeners.starting();try {// 封装命令行参数ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);/** 准备环境:* 创建环境完成后回调SpringApplicationRunListener.environmentPrepared()方法,表示* 环境准备完成。*/ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 打印控制台的Spring 字符画Banner printedBanner = printBanner(environment);// 创建IOC容器:ApplicationContext;决定创建web IOC还是普通的IOC容器。context = createApplicationContext();// 创建错误分析对象analyzers = new FailureAnalyzers(context);/** 准备上下文环境,将environment保存到IOC容器中; 而且applyInitializers(),* 回调之前保存的所有的applicationContextInitializer的initialize()方法;* 回调所有的SpringApplicationRunListener的contextPrepareded();最后回调* 所有的SpringApplicationRunListener的contextLoaded()方法*/prepareContext(context, environment, listeners, applicationArguments, printedBanner);/** 刷新容器:IOC容器的初始化(扫描所有的配置类、@Bean等,加载并创建IOC容器中所有的组件。如果是web应用,* 还会创建嵌入式的tomcat),当执行完refreshContext()后,IOC容器即创建完毕*/refreshContext(context);/** 从IOC容器中获取所有的ApplicationRunner和CommandLineRunner,* 然后先回调ApplicationRunner 再回调 CommandLineRunner*/afterRefresh(context, applicationArguments);// 所有的SpringApplicationRunListener回调finished()方法listeners.finished(context, null);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 整个Spring Boot应用启动完成后,返回IOC容器return context;} catch (Throwable ex) {handleRunFailure(context, listeners, analyzers, ex);throw new IllegalStateException(ex);}
}

四、总结

Spring Boot 的启动流程是:

1、准备环境

2、刷新启动IOC容器: 

3、回调容器中所有的 ApplicationRunner 、CommandLineRunner 的 run() 方法

4、监听器 SpringApplicationRunListener 回调 finished()方法

在“详细启动流程” 中,已经将run()方法中实际执行流程用注释的方式标记出来了,里面的方法都通过调用的方式完成了一些特定的功能,最主要的是把握他们的执行顺序和完成内容,可以通过debug的方式,并观察控制台输出和参数内容来进行追踪学习。

综上,就是关于Spring Boot启动的完整流程,欢迎文末留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558864.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot————应用启动时的监听机制测试

引言 本文承接前面的《Spring Boot————Spring Boot启动流程分析》,主要测试一下ApplicationContextInitializer、SpringApplicationRunListener、ApplicationRunner、CommandLineRunner这四个接口实现之下的组件是何时在Spring Boot项目启动时创建并执行相关方…

2018年度总结

2018年,已经成为过去式,这360多天依旧过的很快,快到当我手扶键盘回想这一年发生的点点滴滴时,都没有任何感慨。可能我天生是个无感之人,或许,这一年的时光,无数的事故、故事已经让我变得不那么感…

Spring Boot————默认缓存应用及原理

引言 应用程序的数据除了可以放在配置文件中、数据库中以外,还会有相当一部分存储在计算机的内存中,这部分数据访问速度要快于数据库的访问,因此通常在做提升数据访问速度时,会将需要提升访问速度的数据放入到内存中,…

LeetCode算法入门- Multiply Strings -day18

LeetCode算法入门- Multiply Strings -day18 题目介绍 Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. Example 1: Input: num1 “2”, num2 “3” Output: “6” Exampl…

Linux——VMware虚拟机安装CentOS步骤

一、下载CentOS.iso镜像 最地道的下载方式就是通过官网,大多数的网上连接会直接抛出网易、华为的镜像连接,实际上这些连接都可以在官网找到: 官网地址(可直接百度搜索CentOS):https://www.centos.org/ 1…

Spring Boot——Redis安装配置与应用整合

引言 Spring Boot默认以ConcurrentHashMap作为缓存容器,但默认的缓存容器在简单的场景使用还是可以的,而作为NoSQL的代表,Redis可以做内存数据库、消息中间件都是不错的,而且有RedisDesktopManager作为可视化管理工具&#xff0c…

利用Aria2高速下载网盘文件

利用Aria2高速下载网盘文件 方法步骤: 下载文件 解压arial2,运行aria2启动.VBS添加插件,解压BaiduExporter-master.zip在Google浏览器扩展程序中chrome://extensions加载已经解压的扩展程序 选择BaiduExporter进行添加即可,打开…

MySQL——JSON_REPLACE()函数修改JSON属性值

引言 由于对mysql的函数并不了解,之前遇到了一个场景: mysql表中有一个字段res_content 是一个由longtext类型(可以理解为一个更长的varchar)保存的巨大的JSON对象,但是,由于录入的疏忽,导致这…

Spring Boot整合Redis——自定义RedisSerializer

引言 spring boot简单引入redis依赖,并使用RedisTemplate进行对象存储时,需要使存储对象实现Serializable接口,这样才能够成功将对象进行序列化。 RedisTemplate默认使用的序列化机制是JdkSerializationRedisSerializer,但实际开…

交易系统如何确保账簿100%准确

转自廖雪峰老师的《交易系统如何确保账簿100%准确》 这篇文章阐述了一个交易系统中对账功能的关键,即:时刻保证资产负债表总额始终为 0。 交易系统中,对账是一个大问题。对账处理不好,不但需要花费大量的人力去处理账簿&#xff…

通俗易懂的SpringBoot教程---day1---Springboot入门教程介绍

通俗易懂的SpringBoot教程—day1—教程介绍 教程介绍: 初级教程: 一、 Spring Boot入门 二、 Spring Boot配置 三、 Spring Boot与日志 四、 Spring Boot与Web开发 五、 Spring Boot与Docker:Docker容器 六、 Spring Boot与数据访问&#x…

Java 8中获取参数名称

本文转自廖雪峰老师的:《在Java 8中获取参数名称》 在Java 8之前的版本,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比。现在,Java 8开始…

通俗易懂的SpringBoot教程---day2---Springboot配置文件

通俗易懂的SpringBoot教程—day2—Springboot配置文件 1、配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的; •application.properties •application.yml 配置文件的作用:修改SpringBoot自动配置的默认值;Spring…

Could not resolve host: 'localhost 报错解决办法

Could not resolve host: localhost 报错解决办法 面向Windows的: 零基础的我一直卡在这一步骤下: 首先要先在Windows安装curl:安装方式参考:https://blog.csdn.net/weixin_41986096/article/details/86646365 按照完之后&…

当面试官问我————为什么String是final的?

面试官:你好,能看得清下面这张图吗? 我:可以的。 面试官:恩,好的。呃,你能不能说一说为什么String要用final修饰? 我:final意味着不能被继承或者被重写,Str…

当面试官问我————Java是值传递还是引用传递?

面试官:你好,你能说出下面个程序的执行结果吗? public class Test {public static void main(String[] args) {String name "Scott";int age 5;User user new User();user.setName(name);user.setAge(age);System.out.println(…

ubuntu系统下Jenkins和tomcat的安装与配置

ubuntu 安装 JDK ubuntu的安装我们采取最简单的方式安装 直接用apt-get的方式 sudo apt-get install openjdk-8-jdk 安装器会提示你同意 oracle 的服务条款,选择 ok 然后选择yes 即可 ubuntu 安装tomcat8 通过apt安装 tomcat8 sudo apt-get install tomcat8 tomcat8-docs t…

String字符串拼接小例

>>>写出下面程序运行结果: public class StringTest {public static void main(String[] args) {String s1 "Programming";String a "Program";String b "ming";String s2 "Program" "ming";Stri…

看完这篇文章,还不懂nginx,算我输

看完这篇文章,还不懂nginx,算我输 参考:https://mp.weixin.qq.com/s/PeNWaCDf_6gp2fCQa0Gvng 1. Nginx产生~ Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格,以统一资源描述符(Uniform Resources Id…

一篇博客读懂设计模式之---工厂模式

设计模式之—工厂模式 工厂模式: 创建过程: 创建Shape接口 public interface Shape {void draw(); }创建实现类: public class Circle implements Shape {Overridepublic void draw() {System.out.println("this is a circle!"…