首页 > 技术文章 > springboot(十五) 源码分析 —— SpringApplication的run()方法

hlkawa 原文

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");
    }
然后调用 #createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) 方法,创建 org.springframework.boot.BeanDefinitionLoader 对象。关于 BeanDefinitionRegistry 类,感兴趣的小伙伴,可以看一看 :【死磕 Spring】—— IoC 之 BeanDefinition 注册表:BeanDefinitionRegistry (https://blog.csdn.net/Yestar123456/article/details/103510054
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的启动的源码要简单些

推荐阅读