![Spring Boot技术内幕:架构设计与实现原理](https://wfqqreader-1252317822.image.myqcloud.com/cover/121/32436121/b_32436121.jpg)
上QQ阅读APP看书,第一时间看更新
4.1 run方法核心流程
在分析和学习整个run方法的源代码及操作之前,我们先通过图4-1所示的流程图来看一下SpringApplication调用的run方法处理的核心操作都包含哪些。然后,后面的章节我们再逐步细化分析每个过程中的源代码实现。
![](https://epubservercos.yuewen.com/EF16B1/17517093907485406/epubprivate/OEBPS/Images/4-1.jpg?sign=1739294769-vXg6quUWmCtP8xsQ8XU5tu90sxtVWzzk-0-1c1b95b0563be71bebaf1aa5e6c88d35)
图4-1 run方法核心运行流程图
上面的流程图可以看出,SpringApplication在run方法中重点做了以下操作。
·获取监听器和参数配置。
·打印Banner信息。
·创建并初始化容器。
·监听器发送通知。
当然,除了核心操作,run方法运行过程中还涉及启动时长统计、异常报告、启动日志、异常处理等辅助操作。
对照流程图,我们再来整体看一下入口run方法的源代码,核心部分的功能已通过注释的形式进行说明。
public ConfigurableApplicationContext run(String... args) { // 创建StopWatch对象,用于统计run方法启动时长 StopWatch stopWatch = new StopWatch(); // 启动统计 stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); // 配置headless 属性 configureHeadlessProperty(); // 获得SpringApplicationRunListener 数组 // 该数组封装于SpringApplicationRunListeners对象的listeners中 SpringApplicationRunListeners listeners = getRunListeners(args); // 启动监听,遍历SpringApplicationRunListener数组每个元素,并执行 listeners.starting(); try { // 创建ApplicationArguments对象 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); // 加载属性配置,包括所有的配置属性(如:application.properties中和外部的属性配置) ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); // 打印Banner Banner printedBanner = printBanner(environment); // 创建容器 context = createApplicationContext(); // 异常报告器 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); // 准备容器,组件对象之间进行关联 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 初始化容器 refreshContext(context); // 初始化操作之后执行,默认实现为空 afterRefresh(context, applicationArguments); // 停止时长统计 stopWatch.stop(); // 打印启动日志 if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } // 通知监听器:容器启动完成 listeners.started(context); // 调用ApplicationRunner和CommandLineRunner的运行方法。 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; }
在整体了解了整个run方法运行流程及核心代码后,下面我们针对具体的过程进行讲解。