SpringApplication的run()方法
基于 2.2.9.RELEASE的版本,启动项目debug,当SpringApplication创建完成就开始执行#run(String... args) 方法
public ConfigurableApplicationContext run(String... args) {
// 1.1 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。 StopWatch stopWatch = new StopWatch(); stopWatch.start();
ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 1.2 配置 headless 属性 configureHeadlessProperty();
// 1.3 获得 SpringApplicationRunListener 的数组,并启动监听 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
try {
// 1.4 创建 ApplicationArguments 对象 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 1.5 加载属性配置。执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties 和外部的属性配置。 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment);
// 1.6 打印 Spring Banner Banner printedBanner = printBanner(environment);
// 1.7 创建 Spring 容器。 context = createApplicationContext();
// 1.8 异常报告器 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);
// 1.9 主要是调用所有初始化类的 initialize 方法 prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 1.10 初始化 Spring 容器。 refreshContext(context);
// 1.11 执行 Spring 容器的初始化的后置逻辑。默认实现为空。 afterRefresh(context, applicationArguments);
// 1.12 停止 StopWatch 统计时长 stopWatch.stop();
if (this.logStartupInfo) {
// 1.13 打印 Spring Boot 启动的时长日志。 new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); }
// 1.14 通知 SpringApplicationRunListener 的数组,Spring 容器启动完成。 listeners.started(context);
// 1.15 调用 ApplicationRunner 或者 CommandLineRunner 的运行方法。 callRunners(context, applicationArguments); } catch (Throwable ex) {
// 1.15-1 如果发生异常,则进行处理,并抛出 IllegalStateException 异常 handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try {
// 1.16 通知 SpringApplicationRunListener 的数组,Spring 容器运行中 listeners.running(context); } catch (Throwable ex) {
// 1.16-1 如果发生异常,则进行处理,并抛出 IllegalStateException 异常 handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
1.1
,创建 StopWatch 对象,并调用 StopWatch#run()
方法来启动。
StopWatch 主要用于简单统计 run 启动过程的时长。
1.2
,配置 headless 属性。
这个逻辑,可以无视,和 AWT 相关。如果不清楚AWT,可以看一看:Java的AWT简介(https://www.jianshu.com/p/9167d252657a)
1.3
,调用 #getRunListeners(String[] args)
方法,获得 SpringApplicationRunListener 数组,并启动监听。
代码如下:
private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 1.3.1 return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)); }
1.3.1 SpringApplicationRunListeners SpringApplicationRunListener 数组的封装
SpringApplication 运行的监听器接口。
class SpringApplicationRunListeners { private final Log log;
// SpringApplicationRunListener 数组 private final List<SpringApplicationRunListener> listeners; SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) { this.log = log; this.listeners = new ArrayList<>(listeners); } void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } } void environmentPrepared(ConfigurableEnvironment environment) { for (SpringApplicationRunListener listener : this.listeners) { listener.environmentPrepared(environment); } } void contextPrepared(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.contextPrepared(context); } } void contextLoaded(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.contextLoaded(context); } } void started(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.started(context); } } void running(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.running(context); } } void failed(ConfigurableApplicationContext context, Throwable exception) { for (SpringApplicationRunListener listener : this.listeners) { callFailedListener(listener, context, exception); } } private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context, Throwable exception) { try { listener.failed(context, exception); } catch (Throwable ex) { if (exception == null) { ReflectionUtils.rethrowRuntimeException(ex); } if (this.log.isDebugEnabled()) { this.log.error("Error handling failed", ex); } else { String message = ex.getMessage(); message = (message != null) ? message : "no error message"; this.log.warn("Error handling failed (" + message + ")"); } } } }
目前,SpringApplicationRunListener 的实现类,只有 EventPublishingRunListener 类。org.springframework.boot.context.event.EventPublishingRunListener ,实现 SpringApplicationRunListener、Ordered 接口,将 SpringApplicationRunListener 监听到的事件,转换成对应的 SpringApplicationEvent 事件,发布到监听器们。
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
// Spring 应用 private final SpringApplication application;
// 参数集合 private final String[] args;
// 事件广播器 private final SimpleApplicationEventMulticaster initialMulticaster; public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } } @Override public int getOrder() { return 0; } @Override public void starting() { this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); } @Override public void environmentPrepared(ConfigurableEnvironment environment) { this.initialMulticaster .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment)); } @Override public void contextPrepared(ConfigurableApplicationContext context) { this.initialMulticaster .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context)); } @Override public void contextLoaded(ConfigurableApplicationContext context) { for (ApplicationListener<?> listener : this.application.getListeners()) { if (listener instanceof ApplicationContextAware) { ((ApplicationContextAware) listener).setApplicationContext(context); } context.addApplicationListener(listener); } this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context)); } @Override public void started(ConfigurableApplicationContext context) { context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context)); } @Override public void running(ConfigurableApplicationContext context) { context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context)); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception); if (context != null && context.isActive()) { // Listeners have been registered to the application context so we should // use it at this point if we can context.publishEvent(event); } else { // An inactive context may not have a multicaster so we use our multicaster to // call all of the context's listeners instead if (context instanceof AbstractApplicationContext) { for (ApplicationListener<?> listener : ((AbstractApplicationContext) context) .getApplicationListeners()) { this.initialMulticaster.addApplicationListener(listener); } } this.initialMulticaster.setErrorHandler(new LoggingErrorHandler()); this.initialMulticaster.multicastEvent(event); } } private static class LoggingErrorHandler implements ErrorHandler { private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class); @Override public void handleError(Throwable throwable) { logger.warn("Error calling ApplicationEventListener", throwable); } } }
debug listeners的值如下图
1.4,创建 ApplicationArguments 对象。
感兴趣的朋友可以看一看:ApplicationArguments 类(https://www.hxstrive.com/subject/spring_boot.htm?id=334)
1.5,调用 #prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments)
方法,加载属性配置
执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties
和外部的属性配置。#prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) 方法,加载属性配置。
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // 1.5.1 创建 ConfigurableEnvironment 对象,并进行配置 ConfigurableEnvironment environment = getOrCreateEnvironment(); configureEnvironment(environment, applicationArguments.getSourceArgs());
// 1.5.2 如果有 attach 到 environment 上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中 ConfigurationPropertySources.attach(environment);
// 1.5.3 通知 SpringApplicationRunListener 的数组,环境变量已经准备完成 listeners.environmentPrepared(environment);
// 1.5.4 绑定 environment 到 SpringApplication 上 bindToSpringApplication(environment); if (!this.isCustomEnvironment) {
// 1.5.5 如果非自定义 environment ,则根据条件转换 environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); }
// 1.5.6 同1.5.2 ConfigurationPropertySources.attach(environment); return environment; }
1.5.1,调用 #getOrCreateEnvironment()
方法,创建 ConfigurableEnvironment 对象
private ConfigurableEnvironment getOrCreateEnvironment() {
// 已经存在,则进行返回 if (this.environment != null) { return this.environment; }
// 不存在,则根据 webApplicationType 类型,进行创建 switch (this.webApplicationType) { case SERVLET: return new StandardServletEnvironment(); case REACTIVE: return new StandardReactiveWebEnvironment(); default: return new StandardEnvironment(); } }
然后调用 #configureEnvironment(ConfigurableEnvironment environment, String[] args)
方法,配置 environment
变量。代码如下:
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) { if (this.addConversionService) {
// 1.5.1.1 设置 environment 的 conversionService 属性 ConversionService conversionService = ApplicationConversionService.getSharedInstance(); environment.setConversionService((ConfigurableConversionService) conversionService); }
// 1.5.1.2 增加 environment 的 PropertySource 属性源 configurePropertySources(environment, args);
// 1.5.1.3 配置 environment 的 activeProfiles 属性 configureProfiles(environment, args); }
1.5.1.1
,设置 environment
的 conversionService
属性。可以无视。感兴趣的小伙伴,可以看一看 【死磕 Spring】---- Spring 的环境属性:PropertySource、Environment、Profile(https://cloud.tencent.com/developer/article/1399708)
1.5.1.2,增加 environment 的 PropertySource 属性源
代码如下:可以根据配置的 defaultProperties、或者 JVM 启动参数,作为附加的 PropertySource 属性源。
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) { MutablePropertySources sources = environment.getPropertySources();
// 配置的 defaultProperties if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) { sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties)); }
// 来自启动参数的 if (this.addCommandLineProperties && args.length > 0) { String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
// 如果存在就替换,不存在就创建 if (sources.contains(name)) { PropertySource<?> source = sources.get(name); CompositePropertySource composite = new CompositePropertySource(name); composite.addPropertySource( new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args)); composite.addPropertySource(source); sources.replace(name, composite); } else { sources.addFirst(new SimpleCommandLinePropertySource(args)); } } }
1.5.1.3 配置 environment 的 activeProfiles 属性
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) { Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles); profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
// 设置 activeProfiles environment.setActiveProfiles(StringUtils.toStringArray(profiles)); }
对profile激活的方式感兴趣的小伙伴,可以看一看:Spring boot 激活 profile的几种方式(https://my.oschina.net/u/1469495/blog/1522784)
1.5.3,调用 SpringApplicationRunListeners#environmentPrepared(ConfigurableEnvironment environment) 方法,通知 SpringApplicationRunListener 的数组,环境变量已经准备完成。
1.5.4,调用 #bindToSpringApplication(ConfigurableEnvironment environment) 方法,绑定 environment 到 SpringApplication 上。暂时不太知道用途。
1.5.5,如果非自定义 environment ,则根据条件转换。默认情况下,isCustomEnvironment 为 false ,所以会执行这块逻辑。但是,一般情况下,返回的还是 environment 自身,所以可以无视这块逻辑先。
1.5.2/1.5.6,调用 ConfigurationPropertySources#attach(Environment environment) 静态方法,如果有 attach 到 environment上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中。这块逻辑,也可以先无视。
1.6,调用 #printBanner(ConfigurableEnvironment environment)
方法,打印 Spring Banner
具体的代码实现,就先不分析了。
1.7,调用 #createApplicationContext() 方法,创建 Spring 容器
根据 webApplicationType 类型,获得对应的 ApplicationContext 对象
protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try {
// 根据 webApplicationType 类型,获得 ApplicationContext 类型 switch (this.webApplicationType) { case SERVLET:
// org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE:
// org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default:
// org.springframework.context.annotation.AnnotationConfigApplicationContext contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } }
// 创建ApplicationContext对象 return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }
1.8,通过 #getSpringFactoriesInstances(Class<T> type) 方法,进行获得 SpringBootExceptionReporter 类型的对象数组
SpringBootExceptionReporter ,记录启动过程中的异常信息。exceptionReporters,debug结果如下:
1.9,调用 #prepareContext(...) 方法,主要是调用所有初始化类的 #initialize(...) 方法
该方法主要是给 context 的属性做赋值,以及 ApplicationContextInitializer 的初始化。
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { // 1.9.1 设置 context 的 environment 属性 context.setEnvironment(environment); // 1.9.2 设置 context 的一些属性 postProcessApplicationContext(context); // 1.9.3 初始化 ApplicationContextInitializer applyInitializers(context); // 1.9.4 通知 SpringApplicationRunListener 的数组,Spring 容器准备完成 listeners.contextPrepared(context); // 1.9.5 打印日志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans // 1.9.6 设置 beanFactory 的属性 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); }
// Load the sources // 1.9.7 加载 BeanDefinition 们 Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[0]));
// 1.9.8 通知 SpringApplicationRunListener 的数组,Spring 容器加载完成 listeners.contextLoaded(context); }
1.9.1,设置 context 的 environment 属性
1.9.2,调用 #postProcessApplicationContext(ConfigurableApplicationContext context) 方法,设置 context 的一些属性
protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator != null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }
1.9.3,调用 #applyInitializers(ConfigurableApplicationContext context) 方法,遍历 ApplicationContextInitializer 数组,逐个调用 ApplicationContextInitializer#initialize(context) 方法,进行初始化。
@SuppressWarnings({ "rawtypes", "unchecked" }) protected void applyInitializers(ConfigurableApplicationContext context) { // 遍历 ApplicationContextInitializer 数组 for (ApplicationContextInitializer initializer : getInitializers()) { // 校验 ApplicationContextInitializer 的泛型非空 Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, "Unable to call initializer."); // 初始化 ApplicationContextInitializer initializer.initialize(context); } }
1.9.4,调用 SpringApplicationRunListeners#contextPrepared(ConfigurableApplicationContext context) 方法,通知 SpringApplicationRunListener 的数组,Spring 容器准备完成。
1.9.5,打印日志。效果如下:
2020-12-18 05:31:02.766 INFO 59714 --- [ main] com.brian.demo.DemoApplication : Starting DemoApplication on brian-System-Product-Name with PID 59714 (/home/brian/桌面/just-do-it/code/springdoc-test/target/classes started by brian in /home/brian/桌面/just-do-it/code/springdoc-test)
2020-12-18 05:31:05.473 INFO 59714 --- [ main] com.brian.demo.DemoApplication : No active profile set, falling back to default profiles: default
1.9.6,设置 beanFactory 的属性。
1.9.7,调用 #load(ApplicationContext context, Object[] sources) 方法,加载 BeanDefinition 们。
protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } // 1.9.7.1 创建 BeanDefinitionLoader 对象 BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); // 1.9.7.2 设置 loader 的属性 if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } // 1.9.7.3 执行 BeanDefinition 加载 loader.load(); }
1.9.7.1,调用 #getBeanDefinitionRegistry(ApplicationContext context) 方法,创建 BeanDefinitionRegistry 对象.
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) { if (context instanceof BeanDefinitionRegistry) { return (BeanDefinitionRegistry) context; } if (context instanceof AbstractApplicationContext) { return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory(); } throw new IllegalStateException("Could not locate BeanDefinitionRegistry"); }
1.9.7.2,设置 loader 的属性。
1.9.7.3,调用 BeanDefinitionLoader#load() 方法,执行 BeanDefinition 加载。关于BeanDefinition,感兴趣的小伙伴可以看一看 【死磕 Spring】—— IoC 之加载 BeanDefinition :(https://blog.csdn.net/chenssy/article/details/82494923)
1.9.8,调用 SpringApplicationRunListeners#contextLoaded(ConfigurableApplicationContext context) 方法,通知 SpringApplicationRunListener 的数组,Spring 容器加载完成。
1.10,调用 ``#refreshContext(ConfigurableApplicationContext context)` 方法,启动(刷新) Spring 容器
private void refreshContext(ConfigurableApplicationContext context) { // 1.10.1 开启(刷新)Spring 容器 refresh(context); // 1.10.2 注册 ShutdownHook 钩子 if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }
1.10.1 处,调用 #refresh(ApplicationContext applicationContext) 方法,开启(刷新)Spring 容器
protected void refresh(ApplicationContext applicationContext) { // 断言,判断 applicationContext 是 AbstractApplicationContext 的子类 Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); // 启动(刷新) AbstractApplicationContext ((AbstractApplicationContext) applicationContext).refresh(); }
关于AbstractApplicationContext感兴趣的小伙伴可以看一看:Spring源码分析之从refresh方法分析Spring的IoC原理 (https://blog.csdn.net/MOKEXFDGH/article/details/100731781)
1.10.2,调用 ConfigurableApplicationContext#registerShutdownHook() 方法,注册 ShutdownHook 钩子。这个钩子,主要用于 Spring 应用的关闭时,销毁相应的 Bean 们。
1.11,调用 #afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) 方法,执行 Spring 容器的初始化的后置逻辑
默认实现是个空方法
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { }
1.12,停止 StopWatch 统计时长
1.13,打印 Spring Boot 启动的时长日志。效果如下:
2020-12-17 07:09:09.382 INFO 36276 --- [ main] com.brian.demo.DemoApplication : Started DemoApplication in 33.92 seconds (JVM running for 40.273)
1.14,调用 SpringApplicationRunListeners#started(ConfigurableApplicationContext context) 方法,通知 SpringApplicationRunListener 的数组,Spring 容器启动完成
1.15,调用 #callRunners(ApplicationContext context, ApplicationArguments args) 方法,调用 ApplicationRunner 或者 CommandLineRunner 的运行方法
代码如下:
private void callRunners(ApplicationContext context, ApplicationArguments args) { // 获得所有 Runner 们 List<Object> runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); // 排序 runners AnnotationAwareOrderComparator.sort(runners); // 遍历 Runner 数组,执行逻辑 for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
关于callRunner方法代码如下:
private void callRunner(ApplicationRunner runner, ApplicationArguments args) { try { (runner).run(args); } catch (Exception ex) { throw new IllegalStateException("Failed to execute ApplicationRunner", ex); } }
private void callRunner(CommandLineRunner runner, ApplicationArguments args) { try { (runner).run(args.getSourceArgs()); } catch (Exception ex) { throw new IllegalStateException("Failed to execute CommandLineRunner", ex); } }
1.15-1,如果发生异常,则调用 #handleRunFailure(...) 方法,交给 SpringBootExceptionReporter 进行处理,并抛出 IllegalStateException 异常
1.16,调用 SpringApplicationRunListeners#running(ConfigurableApplicationContext context) 方法,通知 SpringApplicationRunListener 的数组,Spring 容器运行中
1.16-1,如果发生异常,则调用 #handleRunFailure(...) 方法,交给 SpringBootExceptionReporter 进行处理,并抛出 IllegalStateException 异常。
到这里整个run方法分析就完毕了,相比Spring的启动的源码要简单些