SpringBoot启动

SpringApplication.run一共做了两件事,一件是创建SpringApplication对象,在该对象初始化时,找到配置的事件监听器,并保存起来.第二件事就是运行run方法,此时会将刚才保存的事件监听器根据当前时机触发不同的事件,比如容器初始化,容器创建完成等.同时也会刷新IoC容器,进行组件的扫描、创建、加载等工作.这两件事我都看过源码,我分别给你画个图细致讲一讲.

SpringApplication.run

SpringApplication.run一共做了两件事,分别是

  • 创建SpringApplication对象
  • 利用创建好的SpringApplication对象,调用run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
    return new SpringApplication(sources).run(args);
}

public SpringApplication(Object... sources) {
    initialize(sources);
}

创建SpringApplication对象

  1. 保存主配类
  2. 判断当前是否为web应用
  3. 从类路径下找到/META-INF/spring.factories配置的所有ApplicationContextInitializer。并保存。
  4. 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener。并保存。
  5. 从配置类中找到main方法的主配置类
private void initialize(Object[] sources) {
    //1.保存主配类
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //2. 判断当前是否为web应用
    this.webEnvironment = deduceWebEnvironment();
    //从类路径下找到/META-INF/spring.factories配置的所有ApplicationContextInitializer。并保存。
    setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
    //从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener。并保存。
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

调用run方法

  1. 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener.
  2. 遍历所有ApplicationListener然后回调其starting事件。
  3. 封装命令行参数
  4. 准备环境,并遍历回调SpringApplicationRunListeners的environmentPrepared事件
  5. Banner打印.
  6. 根据是否是web环境来决定创建web容器还是普通的IOC容器
  7. 准备上下文环境,将environment保存到IOC容器当中
  • 7-1. 执行applyInitializers方法:遍历回调ApplicationContextInitializer的initialize事件。
  • 7-2. 遍历回调SpringApplicationRunListeners的contextPrepared事件
  • 7-3. 继续回调SpringApplicationRunListeners的contextLoaded事件
  1. 刷新容器,此时进行组件的扫描,加载,创建等。
  2. 从IOC容器中获取所有实现ApplicationRunner和CommandLineRunner的实现类进行回调事件(先回调:ApplicationRunner,然后回调CommandLineRunner)
  3. 遍历回调SpringApplicationRunListeners的finished事件。
  4. 启动完成,返回IOC容器
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    configureHeadlessProperty();
    //1. 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //2. 遍历所有ApplicationListener然后回调其starting事件
    listeners.starting();
    try {
        //3. 封装命令行参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
        //4. 准备环境,并遍历回调SpringApplicationRunListeners的environmentPrepared事件
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
        //5. Banner打印
        Banner printedBanner = printBanner(environment);
        //6. 根据是否是web环境来决定创建web容器还是普通的IOC容器
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        //7. 准备上下文环境,将environment保存到IOC容器当中
        //7-1. 执行applyInitializers方法:遍历回调ApplicationContextInitializer的initialize事件
        //7-2. 遍历回调SpringApplicationRunListeners的contextPrepared事件
        //7-3. 继续回调SpringApplicationRunListeners的contextLoaded事件
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        //8. 刷新容器,此时进行组件的扫描,加载,创建等。
        refreshContext(context);
        //9. 从IOC容器中获取所有实现ApplicationRunner和CommandLineRunner的实现类进行回调事件(先回调:ApplicationRunner,然后回调CommandLineRunner)
        afterRefresh(context, applicationArguments);
        //10. 遍历回调SpringApplicationRunListeners的finished事件
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
        }
        //11. 启动完成,返回IOC容器
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}

你可能感兴趣的:(SpringBoot启动)