特性

1.自动配置:针对很多Spring应用程序和常见的应用功能,Spring boot能自动提供相关配置;:
2.起步依赖:告诉Spring boot需要什么功能,它就能引入需要的依赖库;
3.Actuator:让你能够深入运行中的Spring Boot应用程序,一探Spring boot程序的内部信息;
4.命令行界面:这是Spring Boot的可选特性,主要针对Groovy语言使用。

启动流程大致分为两步一是对primarySources的准备工作二是运行run步骤

public SpringApplication(Class... primarySources) {
    this((ResourceLoader)null, primarySources);
}

这边主要做了以下 4 个步骤:

  1. 判断当前应用程序的类型 NONE、SERVLET、REACTIVE
  2. 加载所有的初始化容器
  3. 加载所有的监听器
  4. 找到程序运行的主类

方法里面调用的构造方法如下:

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    this.logStartupInfo = true;
    this.addCommandLineProperties = true;
    this.headless = true;
    this.registerShutdownHook = true;
    this.additionalProfiles = new HashSet();
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    this.webApplicationType = this.deduceWebApplicationType();
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = this.deduceMainApplicationClass();
}

接下来就是 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 ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
    //第一步:开启计时器
    //设置当前任务的id和启动的时间,方便后续的时候
    //进行计时的操作
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //设置空值以及异常集合,不是很重要
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();

    //第二步:配置系统属性java.awt.headless意义不大,可以忽略
    configureHeadlessProperty();

    //第三步:获取一个EventPublishingRunListeners的对象,此对象会贯穿整个应用程序启动的过程,每次在进行监听器操作的时候都会从中获取具体的监听器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {

        //第四步:加载命令行的参数值,解析在命令行中通过--key=value输入的属性值,封装到ApplicationArguments对象中
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

        //第五步:准备当前的应用环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

        //第六步:设置系统属性,保证某些bean不会添加到准备的环境中spring.beaninfo.ignore
        configureIgnoreBeanInfo(environment);

        //第七步:准备banner的打印,就是刚开始运行的图片
        Banner printedBanner = printBanner(environment);

        //第八步:准备上下文应用对象,根据当前应用程序的类型来判断创建什么格式的上下文对象
        context = createApplicationContext();

         //第九步:设置异常报告器对象
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
  
        //第十步:设置异常报告器对象 准备当前上下文对象
        //1.设置初始化进行执行,向beanfactory中注入了三个postprocessor的对象,后续在自动装配的时候会用到applylnitializers(context);
        //2.listeners.contextPrepared(context);
        //3.加载很多资源配置,自动装配在此环节完成load(context,sources.toArray(new Object[]);
        //4.listeners.contextLoaded(context);
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);

        //第十一步:刷新上下文环境(关键操作),已经在spring的时候会讲到
        refreshContext(context);

        //第十二步:上下文对象准备好之后的操作,默认什么都不做,方便扩展
        afterRefresh(context, applicationArguments);

        //第十三步:计时结束,并打印启动程序运行的时长
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        //第十四步:开始所有的监听器对象
        listeners.started(context);
        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;
}

同时附上关于 SpringBoot 的启动原理图:

20220530232544.png

原文: