Java Spring Boot SpringApplication.run执行流程

SpringApplication.run执行流程

原文参考 https://blog.csdn.net/CHS007chs/article/details/80534606

  • 1、这个方法里面首先创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
    • 1、根据classpath里面是否存在某个特征类来决定web应用类型,这个类型会用来创建相应的ApplicationContext
    • 2、使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer
    • 3、使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener
    • 4、推断并设置main方法的定义类
  • 2、SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,首先遍历所有通过SpringFactoriesLoader加载的SpringApplicationRunListener,调用它们的started方法。
  • 3、创建并配置当前Spring Boot应用将要使用的Environment
  • 4、遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法
  • 5、如果SpringApplication的showBanner属性被设置为true,则打印banner
  • 6、根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,最重要的,是将之前准备好的Environment设置给创建好的ApplicationContext使用
  • 7、ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicatinContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法对已经创建好的ApplicationContext进行进一步的处理
  • 8、遍历调用所有SpringApplicationRunListener的contextPrepared()方法
  • 9、最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext
  • 10、遍历调用所有SpringApplicationRunListener的contextLoaded()方法
  • 11、调用ApplicationContext的refresh()方法,完成IoC容器可用的最后上道工序
  • 12、查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们
  • 13、正常情况下,遍历执行SpringApplicationRunListener的方法表示启动完成(如果整个过程出现异常,会把异常信息也传给listener) 生命周期

springboot启动类——SpringApplication.run()详解

原文参考 https://blog.csdn.net/weixin_41884010/article/details/88844946

启动类

@SpringBootApplication
public class SpringTestApplication {

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

}

SpringTestApplication类执行main方法,main方法调用SpringApplication的run方法。

run方法干了两件事:

  • 创建SpringApplication对象
  • 利用创建好的SpringApplication对象调用run方法

创建SpringApplication对象

在执行SpringApplication的run方法时首先会创建一个SpringApplication类的对象,利用构造方法创建SpringApplication对象时会调用initialize方法。

SpringApplication.run()方法的基本调用流程:

private void initialize(Object[] sources) {
    // 在sources不为空时,保存配置类
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    // 判断是否为web应用
    this.webEnvironment = deduceWebEnvironment();
    // 获取并保存容器初始化类,通常在web应用容器初始化使用
    // 利用loadFactoryNames方法从路径MEAT-INF/spring.factories中找到所有的ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    // 获取并保存监听器
    // 利用loadFactoryNames方法从路径MEAT-INF/spring.factories中找到所有的ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 从堆栈信息获取包含main方法的主配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}

initialize方法:

private void initialize(Object[] sources) {
    // 在sources不为空时,保存配置类
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    // 判断是否为web应用
    this.webEnvironment = deduceWebEnvironment();
    // 获取并保存容器初始化类,通常在web应用容器初始化使用
    // 利用loadFactoryNames方法从路径MEAT-INF/spring.factories中找到所有的ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    // 获取并保存监听器
    // 利用loadFactoryNames方法从路径MEAT-INF/spring.factories中找到所有的ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 从堆栈信息获取包含main方法的主配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}

调用run方法

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    // 配置属性
    configureHeadlessProperty();
    // 获取监听器
    // 利用loadFactoryNames方法从路径MEAT-INF/spring.factories中找到所有的SpringApplicationRunListener
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 启动监听
    // 调用每个SpringApplicationRunListener的starting方法
    listeners.starting();
    try {
        // 将参数封装到ApplicationArguments对象中
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        // 准备环境
        // 触发监听事件——调用每个SpringApplicationRunListener的environmentPrepared方法
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
        // 从环境中取出Banner并打印
        Banner printedBanner = printBanner(environment);
        // 依据是否为web环境创建web容器或者普通的IOC容器
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        // 准备上下文
        // 1.将environment保存到容器中
        // 2.触发监听事件——调用每个SpringApplicationRunListeners的contextPrepared方法
        // 3.调用ConfigurableListableBeanFactory的registerSingleton方法向容器中注入applicationArguments与printedBanner
        // 4.触发监听事件——调用每个SpringApplicationRunListeners的contextLoaded方法
        prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
        // 刷新容器,完成组件的扫描,创建,加载等
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        // 触发监听事件——调用每个SpringApplicationRunListener的finished方法
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        // 返回容器
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}

总结

SpringApplication.run一共做了两件事

  • 1、创建SpringApplication对象;在对象初始化时保存事件监听器,容器初始化类以及判断是否为web应用,保存包含main方法的主配置类。
  • 2、调用run方法;准备spring的上下文,完成容器的初始化,创建,加载等。会在不同的时机触发监听器的不同事件。

原文参考文献