public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
	return new SpringApplication(sources).run(args);
}

1、启动流程:

 1、创建SpringApplication对象(new SpringApplication(sources))

通过构造器调用initialize(sources);方法

public SpringApplication(Object... sources) {
	initialize(sources);
}
initialize(sources):
private void initialize(Object[] sources) {
    //保存主配置类
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判断当前是否一个web应用
    this.webEnvironment = deduceWebEnvironment();
    //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    //从类路径下找到ETA-INF/spring.factories配置的所有ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //从多个配置类中找到有main方法的主配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}

①setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)):

从类路径下的META-INF/spring.factories中拿到配置的所有ApplicationContextInitializer

例子:

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_spring

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_System_02

 方法执行完成后,拿到的所有的Initializers:

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_System_03

②setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));:

从类路径下META-INF/spring.factories拿到配置的所有ApplicationListener

例子:

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_spring_04

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_spring_05

  方法执行完成后,拿到的所有的Listener

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_System_06

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_ide_07

 


2、运行run方法(.run(args))

run方法:
public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   //声明一个ioc容器
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
    
   //获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //回调所有的SpringApplicationRunListener.starting()方法
   listeners.starting();
   try {
       //封装命令行参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //准备环境
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
       		//创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
       
      Banner printedBanner = printBanner(environment);
       
       //创建ApplicationContext;决定创建web的ioc还是普通的ioc
      context = createApplicationContext();
       
      analyzers = new FailureAnalyzers(context);
       //准备上下文环境;将environment保存到ioc中;而且applyInitializers();
       //applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法
       //回调所有的SpringApplicationRunListener的contextPrepared();
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
       //prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
       
       //刷新容器,ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat)
       //扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
      refreshContext(context);
       //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
       //ApplicationRunner先回调,CommandLineRunner再回调
      afterRefresh(context, applicationArguments);
       //所有的SpringApplicationRunListener回调finished方法
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
       //整个SpringBoot应用启动完成以后返回启动的ioc容器;
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}


步骤的解析:

1)、SpringApplicationRunListeners listeners = getRunListeners(args);:

获取SpringApplicationRunListeners,从类路径下META-INF/spring.factories

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_System_08

 

2)、listeners.starting();

回调所有的SpringApplicationRunListener.starting()方法

 

3)、new DefaultApplicationArguments(args);

封装命令行参数

 

4)、prepareEnvironment(listeners,applicationArguments);

创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成

 

5)、printBanner(environment);

打印spring图标

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_ide_09

 

6)、createApplicationContext();

创建ApplicationContext,决定创建web的ioc还是普通的ioc

 

7)、prepareContext(context, environment, listeners, applicationArguments,printedBanner);

准备上下文环境,将environment保存到ioc中,而且调用了applyInitializers();

        ① applyInitializers();

          回调之前保存的所有的ApplicationContextInitializer的initialize()方法

然后回调SpringApplicationRunListener.contextPrepared(context);方法,

运行到最后一步回调SpringApplicationRunListener.contextLoaded(context);方法

 

8)、 refreshContext(context);

刷新容器,ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat)

扫描,创建,加载所有组件的地方(配置类,组件,自动配置)

 

9)、 afterRefresh(context, applicationArguments);

 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调

ApplicationRunner先回调,CommandLineRunner再回调

 

10)、listeners.finished(context, null);

所有的SpringApplicationRunListener回调finished()方法

 

11)、 return context;

整个spring boot应用启动完成后,返回ioc容器


2、事件监听机制

在spring boot应用启动中有几个重要的事件回调机制

1.配置在META-INF/spring.factories

1)ApplicationContextInitializer
public class HelloApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("HelloApplicationContextInitializer.........initialize" + applicationContext);
    }
}
2)SpringApplicationRunListener(必须要有一个(SpringApplication application, String[] args)参数的构造器,否则会出错)
public class HelloSpringApplicationRunListener implements SpringApplicationRunListener {

    //必须有的构造器
    public HelloSpringApplicationRunListener(SpringApplication application, String[] args){

    }

    @Override
    public void starting() {
        System.out.println("HelloSpringApplicationRunListener...starting");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println("HelloSpringApplicationRunListener...environmentPrepared");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("HelloSpringApplicationRunListener...contextPrepared");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("HelloSpringApplicationRunListener...contextLoaded");
    }

    @Override
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("HelloSpringApplicationRunListener...finished");
    }
}
在META-INF中的spring.factories中配置
org.springframework.context.ApplicationContextInitializer=\
  com.it.springboot.listener.HelloApplicationContextInitializer

org.springframework.boot.SpringApplicationRunListener=\
  com.it.springboot.listener.HelloSpringApplicationRunListener
 
2.只需要放在ioc容器中
1)、ApplicationRunner
@Component
public class HelloApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("HelloApplicationRunner....run");
    }
}
2)、CommandLineRunner
@Component
public class HelloCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("HelloCommandLineRunner....run");
    }
}

执行结果:

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_spring_10

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_System_11

springboot中监听文件夹是否存在新建文件 springboot启动监听线程_ide_12