SpringBoot启动流程源码分析

时间:2020-7-29 作者:admin


源码分析

在SpringApplication.run(SystemmanageApplication.class, args) 入口打个断点,debug进去。
SpringBoot启动流程源码分析

继续Debug
SpringBoot启动流程源码分析
SpringBoot启动流程源码分析

执行new SpringApplication() 调用了构造方法,进行初始化操作

SpringBoot启动流程源码分析

  1. 判断了当前类型是否web
  2. 加载所有的初始化器
  3. 加载所有的监听器
  4. 设置程序运行的主类

执行run方法

定位到public ConfigurableApplicationContext run(String… args)方法,开始分析吧

public ConfigurableApplicationContext run(String... args) {
    // 创建并启动计时监控类
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    // 声明应用上下文对象和异常报告集合
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    // 设置系统属性 headless 的值
    this.configureHeadlessProperty();
    // 创建所有 Spring 运行监听器并发布应用启动事件
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();
    Collection exceptionReporters;
    try {
        // 处理 args 参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 准备环境
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        // 创建 Banner 的打印类
        Banner printedBanner = this.printBanner(environment);
        // 创建应用上下文
        context = this.createApplicationContext();
        // 实例化异常报告器
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        // 准备应用上下文
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 刷新应用上下文
        this.refreshContext(context);
        // 应用上下文刷新之后的事件的处理
        this.afterRefresh(context, applicationArguments);
        // 停止计时监控类
        stopWatch.stop();
        // 输出日志记录执行主类名、时间信息
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }
        // 发布应用上下文启动完成事件
        listeners.started(context);
        // 执行所有 Runner 运行器
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }
    try {
        // 发布应用上下文就绪事件
        listeners.running(context);
        // 返回应用上下文对象
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}

流程详解

以上就是Springboot启动的流程,可以将其划分为18步。具体如下:

1.创建并启动计时监控类
org.springframework.util下的StopWatch类
此计时器是为了监控并记录 Spring Boot 应用启动的时间的,它会记录当前任务的名称,然后开启计时器。

2.声明应用上下文对象和异常报告集合

此过程声明了应用上下文对象。
同时声明了异常报告集合用于收集错误信息,用于向用户报告错误原因。

3.设置系统属性 headless 的值
源码如下:

private void configureHeadlessProperty() {
	//此处调用的是:java.awt.headless
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}

系统赋值

public static String setProperty(String key, String value) {
    //判断空操作
    checkKey(key);
    //获取安全管理员 默认null
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new PropertyPermission(key,
            SecurityConstants.PROPERTY_WRITE_ACTION));
    }
    //返回
    return (String) props.setProperty(key, value);
}

目的是设置 Java.awt.headless = true,其中 awt(Abstract Window Toolkit)的含义是抽象窗口工具集。设置为 true 表示运行一个 headless 服务器,可以用它来作一些简单的图像处理。

4.创建所有 Spring 运行监听器并发布应用启动事件

此过程用于获取配置的监听器名称并实例化所有的类。

5.初始化默认应用的参数类

也就是说声明并创建一个应用参数对象。

6.准备环境

创建配置并且绑定环境(通过 property sources 和 profiles 等配置文件)。

7.创建 Banner 的打印类

Spring Boot 启动时会打印 Banner 图片

此 banner 信息是在 SpringBootBanner 类中定义的,我们可以通过实现 Banner 接口来自定义 banner 信息,然后通过代码 setBanner() 方法设置 Spring Boot 项目使用自己自定义 Banner 信息,或者是在 resources 下添加一个 banner.txt,把 banner 信息添加到此文件中,就可以实现自定义 banner 的功能了。

8.创建应用上下文

根据不同的应用类型来创建不同的 ApplicationContext 上下文对象。

9.实例化异常报告器

它调用的是 getSpringFactoriesInstances() 方法来获取配置异常类的名称,并实例化所有的异常处理类。

10.准备应用上下文

此方法的主要作用是把上面已经创建好的对象,传递给 prepareContext 来准备上下文,例如将环境变量 environment 对象绑定到上下文中、配置 bean 生成器以及资源加载器、记录启动日志等操作。

11.刷新应用上下文

此方法用于解析配置文件,加载 bean 对象,并且启动内置的 web 容器等操作。

12.应用上下文刷新之后的事件处理

	/**
	 * Called after the context has been refreshed.
	 * @param context the application context
	 * @param args the application arguments
	 */
	protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
	}

这个方法的源码是空的,可以做一些自定义的后置处理操作。

13.停止计时监控类

停止此过程第一步中的程序计时器,并统计任务的执行信息。

14.输出日志信息

把相关的记录信息,如类名、时间等信息进行控制台输出。

15.发布应用上下文启动完成事件

触发所有 SpringApplicationRunListener 监听器的 started 事件方法。

16.执行所有 Runner 运行器

执行所有的 ApplicationRunner 和 CommandLineRunner 运行器。

17.发布应用上下文就绪事件

触发所有的 SpringApplicationRunListener 监听器的 running 事件。

18.返回应用上下文对象

到此为止 Spring Boot 的启动程序就结束了,我们就可以正常来使用 Spring Boot 框架了。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。