启动项目

SpringBoot项目有一个主程序启动类,在主程序启动勒种有个启动项目main()方法,通过执行SpringApplication.run()启动整个SpringBoot程序

  1. @SpringBootApplication
  2. public class SpringbootDemoApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(SpringbootDemoApplication.class, args);
  5. }
  6. }
  1. public static ConfigurableApplicationContext run(Class<?> primarySource,
  2. String... args) {
  3. return run(new Class[]{primarySource}, args);
  4. }
  5. public static ConfigurableApplicationContext run(Class<?>[] primarySources,
  6. String[] args) {
  7. return (new SpringApplication(primarySources)).run(args);
  8. }

从源码中可以看出来,SpringApplication.run()方法内部执行了两个操作,分别是SpringApplication实例的初始化和调用run()启动项目

SpringApplication实例的初始化

  1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  2. this.resourceLoader = resourceLoader;
  3. Assert.notNull(primarySources, "PrimarySources must not be null");
  4. //把项目启动类.class设置为属性存储起来
  5. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  6. //判断当前webApplicationType应用的类型
  7. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  8. //初始化器,最后会调用这些初始化器
  9. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  10. //设置监听器
  11. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  12. //用于推断并设置项目main()方法启动主程序启动类
  13. this.mainApplicationClass = deduceMainApplicationClass();
  14. }

从上诉源码中可以看出来,SpringApplication的初始化过程包括4部分

  1. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

用于判断webApplicationType应用的类型。deduceFromClasspath()方法用于插手Classpath类路径下是否存在某个特征类,从而判断当前webApplicationType类似是SERVLETyingy (Spring5之前的传统MVC应用)还是REACTIVE应用(Spring5开始出现的WebFlux交互式应用)

  1. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

用于SpringApplication应用的初始化器设置。在初始化器设置的过程中,会使用Spring类加载器SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationContextInitializer

  1. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

用于SpringApplication应用的监听器设置。监听器设置的过程与上一步初始化器设置基本一样,也是使用SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationListener。

  1. this.mainApplicationClass = deduceMainApplicationClass();

用于推断并设置项目main(0方法启动的主程序启动类

项目初始化

  1. public ConfigurableApplicationContext run(String... args) {
  2. StopWatch stopWatch = new StopWatch();
  3. stopWatch.start();
  4. ConfigurableApplicationContext context = null;
  5. Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
  6. configureHeadlessProperty();
  7. //第一步 获取并启动监听器
  8. SpringApplicationRunListeners listeners = getRunListeners(args);
  9. listeners.starting();
  10. try {
  11. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  12. //第二步 根据SpringApplicationRunListeners以及参数来准备环境
  13. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  14. configureIgnoreBeanInfo(environment);
  15. Banner printedBanner = printBanner(environment);
  16. //第三步 创建Spring容器
  17. context = createApplicationContext();
  18. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
  19. new Class[] { ConfigurableApplicationContext.class }, context);
  20. //第四步 容器前置处理
  21. prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  22. //第五步 刷新容器
  23. refreshContext(context);
  24. //第六步 容器后置处理
  25. afterRefresh(context, applicationArguments);
  26. stopWatch.stop();
  27. if (this.logStartupInfo) {
  28. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
  29. }
  30. //第七步 发出结束执行的事件
  31. listeners.started(context);
  32. callRunners(context, applicationArguments);
  33. }
  34. catch (Throwable ex) {
  35. handleRunFailure(context, ex, exceptionReporters, listeners);
  36. throw new IllegalStateException(ex);
  37. }
  38. try {
  39. listeners.running(context);
  40. }
  41. catch (Throwable ex) {
  42. handleRunFailure(context, ex, exceptionReporters, null);
  43. throw new IllegalStateException(ex);
  44. }
  45. return context;
  46. }

SpringBoot执行流程图

image.png