飞道的博客

【Springboot深入解析】框架启动流程

530人阅读  评论(0)

文章仅从源码的角度探讨springboot2.x的原理,不探讨使用。

我们知道Springboot是靠着这段代码进行启动的。

 public static void main(String[] args) {
        SpringApplication.run(XxxApplication.class, args);
    }

分析源码的话,理所当然从这里下手。

通过定位到源码,我们发现这里有两步。一步是初始化SpringApplication对象,一步是调用run方法进行来完成启动。

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

对于SpringApplication初始化的源码,主要就是对相关的属性进行赋值。(this.xxx = xxx)

下面看一下run方法,它的内容非常简短:

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            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);
            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的启动,本质就是初始化SpringApplication对象后,调用run方法。在扣细节之前,有必要整体认识一下springboot启动做了哪些事情:

框架初始化分为:

  1. 配置资源加载器
  2. 配置primarySources(一般是我们的启动类)
  3. 应用环境的检测(springboot1.x版本有两种环境,标准环境和web环境,spingboot2.x添加了一种Reactive环境)
  4. 配置系统初始化器
  5. 配置应用监听器
  6. 配置main方法所在类

接着就是框架的基本启动

  1. 计时器开始计时
  2. Headless模式赋值
  3. 发送ApplicationStartingEvent
  4. 配置环境模块
  5. 发送ApplicationEnvironmentPreparedEvent
  6. 打印banner
  7. 创建应用上下文对象
  8. 初始化失败分析器
  9. 关联springboot组件与应用上下文对象
  10. 发送ApplicationContextInitalizedEvent
  11. 加载sources到context
  12. 发送ApplicationPreparedEvent
  13. 刷新上下文(完成bean的加载)
  14. 计时器停止计时
  15. 发送ApplicationStartedEvent事件
  16. 调用框架启动扩展类
  17. 发送ApplicationReadyEvent

通过以上步骤完成基本的启动,后面还有框架的自动化装配的内容:
  1. 收集配置文件中的配置工厂类
  2. 加载组件工厂
  3. 注册组件内定义 bean

文字描述,可能不太直观,这里用图示整体梳理一下:

下面一起扣细节吧。


转载:https://blog.csdn.net/qq_42322103/article/details/105146224
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场