先来一张图,对SpringBoot启动有个大概了解,再具体对每个方法进行分析.
SpringBoot 启动原理.jpg

mmexport1592729729896.png

通过上图可以看出Spring Boot 启动分为两部分,实例化SpringApplication类、运行run()方法。

  1. public static void main(String[] args) {
  2. SpringApplication.run(MySpringApplication.class, args);
  3. }

1. 实例化SpringApplication

实例化SpringApplication 的内容很简单,只从META-INF/spring.factories中查找并实例化ApplicationContextInitializer、ApplicationListener类型的类,查找具有main()方法的类

  1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  2. this.resourceLoader = resourceLoader;
  3. Assert.notNull(primarySources, "PrimarySources must not be null");
  4. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  5. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  6. // 从META-INF/spring.factories 文件中查找ApplicationContextInitializer类型的实现并实例化
  7. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  8. // 从META-INF/Spring.factories 文件中查找ApplicationListeners 类型的实现并实例化
  9. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  10. // 获取有main()方法的类
  11. this.mainApplicationClass = deduceMainApplicationClass();
  12. }

1.1.查找ApplicationContextInitializer

从META-INF/spring.factories文件中查找所有的org.springframework.context.ApplicationContextInitializer=定义的实现类名称,并实例化这些类。

  1. private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
  2. ClassLoader classLoader = getClassLoader();
  3. // 从META-INF/spring.factories文件中查找key=org.springframework.context.ApplicationContextInitializer的所有值
  4. // 这些值是ApplicationContextInitializer接口实现的的全路径名称
  5. Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  6. // 实例化ApplicationContextInitializer接口实现类
  7. List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
  8. AnnotationAwareOrderComparator.sort(instances);
  9. return instances;
  10. }

1.2. 查找ApplicationListener

查找方式参照查找ApplicationContextInitializer

1.3. 查找main()方法的类

  1. private Class<?> deduceMainApplicationClass() {
  2. try {
  3. StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
  4. for (StackTraceElement stackTraceElement : stackTrace) {
  5. // 查找具有main()方法的类,返回Class
  6. if ("main".equals(stackTraceElement.getMethodName())) {
  7. return Class.forName(stackTraceElement.getClassName());
  8. }
  9. }
  10. }
  11. catch (ClassNotFoundException ex) {
  12. // Swallow and continue
  13. }
  14. return null;
  15. }

1.4. 查找环境类型

SpringBoot的环境类型有三种,分别是NODE、SERVLET、REACTIVE。在启动时需要识别出具体是哪种类型的环境,后面在执行run()方法时,会根据环境实例化不同的容器。

  1. static WebApplicationType deduceFromClasspath() {
  2. // REACTIVE类型
  3. if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
  4. && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
  5. return WebApplicationType.REACTIVE;
  6. }
  7. // NODE类型
  8. for (String className : SERVLET_INDICATOR_CLASSES) {
  9. if (!ClassUtils.isPresent(className, null)) {
  10. return WebApplicationType.NONE;
  11. }
  12. }
  13. // SERVLET类型
  14. return WebApplicationType.SERVLET;
  15. }

2. 运行run()方法

  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. // 获取所有SpringApplicationRunListeners类型的对象
  8. // 从META-INF/spring.factories中获取所有定义好的SpringApplicationRunListeners 全路径名称
  9. // 实例化这些实现类
  10. SpringApplicationRunListeners listeners = getRunListeners(args);
  11. // 执行SpringApplicationRunListener的starting()启动中方法
  12. listeners.starting();
  13. try {
  14. // 封装命令行(main()方法参数)
  15. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  16. // 准备环境
  17. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  18. configureIgnoreBeanInfo(environment);
  19. // 打印Logo
  20. Banner printedBanner = printBanner(environment);
  21. // 根据环境类型创建上下文容器,可以理解为实例化上下文对象
  22. // 环境类型有SERVLET、REACTIVE、NODE
  23. // SERVLET 类型创建org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext对象
  24. // REACTIVE 类型创建org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext对象
  25. // NODE 类型创建org.springframework.context.annotation.AnnotationConfigApplicationContext
  26. context = createApplicationContext();
  27. // 从spring.factories中获取异常处理器
  28. // 当SpringBoot启动失败时,异常处理器会被执行
  29. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
  30. new Class[] { ConfigurableApplicationContext.class }, context);
  31. // 准备上下文,对创建的上下文对象做相应的初始工作
  32. prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  33. // Spring部分,启动SpringIOC容器
  34. refreshContext(context);
  35. // 容器启动完后置处理,空方法由子类实现
  36. afterRefresh(context, applicationArguments);
  37. stopWatch.stop();
  38. if (this.logStartupInfo) {
  39. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
  40. }
  41. // 执行SpringApplicationRunListener 的started()启动完成方法
  42. listeners.started(context);
  43. callRunners(context, applicationArguments);
  44. }
  45. catch (Throwable ex) {
  46. handleRunFailure(context, ex, exceptionReporters, listeners);
  47. throw new IllegalStateException(ex);
  48. }
  49. try {
  50. // 发布应用运行中事件
  51. listeners.running(context);
  52. }
  53. catch (Throwable ex) {
  54. handleRunFailure(context, ex, exceptionReporters, null);
  55. throw new IllegalStateException(ex);
  56. }
  57. return context;
  58. }

2.1. 获取SpringApplicationRunListener

从META-INF/spring.factories中获取SpringApplicationRunListener 定义的类并实例化,这个接口的的作用是在SpringBoot启动过程中,在不同阶段做一些业务处理。

  1. private SpringApplicationRunListeners getRunListeners(String[] args) {
  2. Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
  3. // 首先从META-INF/spring.factories中获取所有SpringApplicationRunListener定义的全类名称
  4. // 然后实例化这些类,返回一个List结合
  5. // 封装到SpringApplicationRunListeners 对象中,在不同的阶段循环的调用对应方法
  6. return new SpringApplicationRunListeners(logger,
  7. getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
  8. }

SpringApplicationRunListener接口定义6个方法,每个方法会在SpringBoot启动的不同阶段执行。

  1. public interface SpringApplicationRunListener {
  2. /**
  3. * 在启动run()方法后立刻调用,可以用于做一些SpringBoot启动前的初始化工作
  4. */
  5. default void starting() {
  6. }
  7. /**
  8. * 在环境准备完成,ApplicationContext上下文容器没有创建之前调用
  9. */
  10. default void environmentPrepared(ConfigurableEnvironment environment) {
  11. }
  12. /**
  13. * ApplicationContext上下文准备完成,准备上下文前调用
  14. */
  15. default void contextPrepared(ConfigurableApplicationContext context) {
  16. }
  17. /**
  18. * 上下文ApplicationContext 准备完成时调用
  19. */
  20. default void contextLoaded(ConfigurableApplicationContext context) {
  21. }
  22. /**
  23. * 在容器刷新(启动)完成,CommandLineRunner和ApplicationRunner 没有被执行前调用
  24. */
  25. default void started(ConfigurableApplicationContext context) {
  26. }
  27. /**
  28. * 在CommandLineRunner和ApplicationRunner被执行后调用,到这里表示SpringBoot已经启动完成
  29. */
  30. default void running(ConfigurableApplicationContext context) {
  31. }
  32. /**
  33. * 在SpringBoot启动出现异常时被调用
  34. */
  35. default void failed(ConfigurableApplicationContext context, Throwable exception) {
  36. }
  37. }

2.1.1. 默认实现EventPublishingRunListener

SprongBoot 为SpringApplicationRunListener接口提供了一个实现类EventPublishingRunListener。它的作用是发送事件,在不同的阶段发送不同的事件,这样监听器就能监听到SpringBoot的启动情况。

  1. public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
  2. private final SpringApplication application;
  3. private final String[] args;
  4. private final SimpleApplicationEventMulticaster initialMulticaster;
  5. /**
  6. * 构造方法,实例化事件广播器,往事件广播器中添加监听器
  7. */
  8. public EventPublishingRunListener(SpringApplication application, String[] args) {
  9. this.application = application;
  10. this.args = args;
  11. // 实例化事件广播器
  12. this.initialMulticaster = new SimpleApplicationEventMulticaster();
  13. // 将监听器添加到事件广播器中
  14. // 这些监听器是在SpringApplication构造方法中,从META-INF/spring.factories中获取的
  15. for (ApplicationListener<?> listener : application.getListeners()) {
  16. this.initialMulticaster.addApplicationListener(listener);
  17. }
  18. }
  19. /**
  20. * 在启动执行run()方法时发布ApplicationStartingEvent事件,用于监听SpringBoot启动前的事件
  21. */
  22. @Override
  23. public void starting() {
  24. this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
  25. }
  26. /**
  27. * 环境准备完成后发布ApplicationEnvironmentPreparedEvent 事件
  28. * @param environment
  29. */
  30. @Override
  31. public void environmentPrepared(ConfigurableEnvironment environment) {
  32. this.initialMulticaster
  33. .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
  34. }
  35. /**
  36. * 在执行完ApplicationContextInitializer初始化方法后,准备上下文容器前发布ApplicationContextInitializedEvent事件
  37. * @param context
  38. */
  39. @Override
  40. public void contextPrepared(ConfigurableApplicationContext context) {
  41. this.initialMulticaster
  42. .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
  43. }
  44. /**
  45. * 上下文容器准备完成后发布ApplicationPreparedEvent 事件
  46. * 将ApplicationListener类型的监听器加到上下文中的事件广播器中
  47. * 注意这里和EventPublishingRunListener构造方法不同的是构造方法是把监听器加入到initialMulticaster事件广播器中
  48. * 这里是把监听器加入到上下文中的事件广播器中,是不同的事件广播器。
  49. * @param context
  50. */
  51. @Override
  52. public void contextLoaded(ConfigurableApplicationContext context) {
  53. // 将事件监听器加入到上下文中的事件广播器中
  54. for (ApplicationListener<?> listener : this.application.getListeners()) {
  55. if (listener instanceof ApplicationContextAware) {
  56. ((ApplicationContextAware) listener).setApplicationContext(context);
  57. }
  58. context.addApplicationListener(listener);
  59. }
  60. // 发布ApplicationPreparedEvent 事件
  61. this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
  62. }
  63. /**
  64. * 容器启动完成后,执行ApplicationRunner和CommandLineRunner的run()方法之前发布ApplicationStartedEvent和AvailabilityChangeEvent事件
  65. * 这里的事件已经不是initialMulticaster事件广播器发布了,是上下文中的事件广播器来发布的
  66. */
  67. @Override
  68. public void started(ConfigurableApplicationContext context) {
  69. context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
  70. AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
  71. }
  72. /**
  73. * 执行完ApplicationRunner和CommandLineRunner的run()方法之后,发布ApplicationReadyEvent和AvailabilityChangeEvent事件
  74. * 事件通过上下文中的事件广播器发布
  75. */
  76. @Override
  77. public void running(ConfigurableApplicationContext context) {
  78. context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
  79. AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
  80. }
  81. /**
  82. * SpringBoot启动失败时执行,发布ApplicationFailedEvent事件
  83. */
  84. @Override
  85. public void failed(ConfigurableApplicationContext context, Throwable exception) {
  86. ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
  87. // 容器处于激活状态,直接发送事件
  88. if (context != null && context.isActive()) {
  89. // 用上下文中的事件广播器发布ApplicationFailedEvent事件
  90. context.publishEvent(event);
  91. }
  92. else {
  93. // 上下文不处于激活状态,采用initialMulticaster 事件广播器发布事件
  94. // 上下文是AbstractApplicationContext类型
  95. // 将监听器加入到initialMulticaster 事件广播器中
  96. if (context instanceof AbstractApplicationContext) {
  97. for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
  98. .getApplicationListeners()) {
  99. this.initialMulticaster.addApplicationListener(listener);
  100. }
  101. }
  102. // 监听器抛出异常时的处理Handler
  103. // 当监听器抛出异常时,通过这个Handler处理一些异常
  104. this.initialMulticaster.setErrorHandler(new org.springframework.boot.context.event.EventPublishingRunListener.LoggingErrorHandler());
  105. // 发布ApplicationFailedEvent 事件
  106. this.initialMulticaster.multicastEvent(event);
  107. }
  108. }
  109. /**
  110. * 监听器抛出异常后处理的Handler
  111. */
  112. private static class LoggingErrorHandler implements ErrorHandler {
  113. private static final Log logger = LogFactory.getLog(org.springframework.boot.context.event.EventPublishingRunListener.class);
  114. @Override
  115. public void handleError(Throwable throwable) {
  116. logger.warn("Error calling ApplicationEventListener", throwable);
  117. }
  118. }
  119. }

2.2. 启动SpringApplicationRunListener.starting()方法

在执行run()方法后,立刻调用starting()方法做一些启动前的初始化工作。因为所有的SpringApplicationRunListener实现类对象都封装在SpringApplicationRunListeners对象中,执行时都是执行这个封装类,在封装类中循环的调用方法。典型的有EventPublishingRunListener实现类,向事件广播器发布ApplicationStartingEvent事件

  1. void starting() {
  2. // 循环调用starting()方法
  3. for (SpringApplicationRunListener listener : this.listeners) {
  4. listener.starting();
  5. }
  6. }

2.3. 准备环境

  1. private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
  2. ApplicationArguments applicationArguments) {
  3. // 根据环境类型获取环境对象
  4. ConfigurableEnvironment environment = getOrCreateEnvironment();
  5. // 配置环境参数
  6. configureEnvironment(environment, applicationArguments.getSourceArgs());
  7. // ???
  8. ConfigurationPropertySources.attach(environment);
  9. // 环境准备完成,执行SpringApplicationRunListener.environmentPrepared()
  10. listeners.environmentPrepared(environment);
  11. bindToSpringApplication(environment);
  12. if (!this.isCustomEnvironment) {
  13. environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
  14. deduceEnvironmentClass());
  15. }
  16. ConfigurationPropertySources.attach(environment);
  17. return environment;
  18. }

2.3.1. 启动SpringApplicationRunListener.enviromentPrepared()

在环境准备完成后,创建上下文之前执行enviromentPrepared()方法

  1. void environmentPrepared(ConfigurableEnvironment environment) {
  2. for (SpringApplicationRunListener listener : this.listeners) {
  3. listener.environmentPrepared(environment);
  4. }
  5. }

2.4. 配置忽略Bean信息

如果没有通过jvm属性配置属性spring.beaninfo.ignore,那么设置属性spring.beaninfo.ignore的值为true

  1. private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
  2. // 如果jvm启动属性配置没有spring.beaninfo.ignore,那么设置默认值为true
  3. if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
  4. // 获取属性spring.beaninfo.ignore的值,默认为true
  5. Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
  6. //设置spring.beaninfo.ignore数值为true
  7. System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
  8. }
  9. }

2.5. 打印Logo

打印SpringBoot启动时的LOGO,可以自己DIY一个打印LOGO

  1. private Banner printBanner(ConfigurableEnvironment environment) {
  2. if (this.bannerMode == Banner.Mode.OFF) {
  3. return null;
  4. }
  5. ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
  6. : new DefaultResourceLoader(getClassLoader());
  7. SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
  8. if (this.bannerMode == Mode.LOG) {
  9. return bannerPrinter.print(environment, this.mainApplicationClass, logger);
  10. }
  11. return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
  12. }

2.6. 创建上下文容器

创建上下文容器,可以理解为实例化一个容器对象。根据环境类型来决定实例化哪个容器对象。容器对象都是ConfigurableApplicationContext类的子类。
环境类型有三种,意味着有三种容器容器对象,分别为:

SERVLET类型:实例化org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext REACTIVE 类型创建org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext NODE 类型创建org.springframework.context.annotation.AnnotationConfigApplicationContext

  1. protected ConfigurableApplicationContext createApplicationContext() {
  2. Class<?> contextClass = this.applicationContextClass;
  3. // 没有指定容器
  4. if (contextClass == null) {
  5. try {
  6. switch (this.webApplicationType) {
  7. case SERVLET:
  8. // SERVLET类型的容器
  9. contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
  10. break;
  11. case REACTIVE:
  12. // REACTIVE 类型的容器
  13. contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
  14. break;
  15. default:
  16. // NONE 类型的容器
  17. contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
  18. }
  19. }
  20. catch (ClassNotFoundException ex) {
  21. throw new IllegalStateException(
  22. "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
  23. }
  24. }
  25. // 实例化容器对象
  26. return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
  27. }

2.7. 获取SpringBootExceptionReporter

SpringBootExceptionReporter 接口的作用是在SpringBoot启动失败时被执行,通过实现该接口,在启动出现异常时,能够做一些启动失败的业务处理。默认实现有FailureAnalyzers类。

  1. // 从spring.factories文件中获取SpringBootExceptionReporter接口的子类全类名称
  2. // 并实例化这些子类
  3. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
  4. new Class[] { ConfigurableApplicationContext.class }, context);

2.8. 准备上下文

在2.6节中,根据环境创建了上下文对象,在这里我们会对上下文对象进行一些准备工作

  1. private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
  2. SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
  3. // 为上下文设置环境对象
  4. context.setEnvironment(environment);
  5. postProcessApplicationContext(context);
  6. // 执行ApplicationContextInitializer接口的初始化方法
  7. applyInitializers(context);
  8. // 执行容器准备完成方法
  9. listeners.contextPrepared(context);
  10. if (this.logStartupInfo) {
  11. logStartupInfo(context.getParent() == null);
  12. logStartupProfileInfo(context);
  13. }
  14. // 获取BeanFactory工程对象
  15. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  16. // 向容器中添加单实例bean applicationArguments对象
  17. beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  18. // 向容器中添加单实例bean printedBanner对象
  19. if (printedBanner != null) {
  20. beanFactory.registerSingleton("springBootBanner", printedBanner);
  21. }
  22. // 如果是DefaultListableBeanFactory bean工厂对象
  23. if (beanFactory instanceof DefaultListableBeanFactory) {
  24. // 当出现bean的名称相同时,允许覆盖bean定义信息的标识
  25. // true 允许覆盖,false不允许覆盖
  26. ((DefaultListableBeanFactory) beanFactory)
  27. .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  28. }
  29. // 添加BeanFactoryPostProcessor 后置处理器LazyInitializationBeanFactoryPostProcessor
  30. // 这个后置处理器的作用是决定是否需要对一些bean进行延迟加载
  31. if (this.lazyInitialization) {
  32. context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  33. }
  34. // Load the sources
  35. Set<Object> sources = getAllSources();
  36. Assert.notEmpty(sources, "Sources must not be empty");
  37. load(context, sources.toArray(new Object[0]));
  38. // 执行容器加载完成方法
  39. listeners.contextLoaded(context);
  40. }

2.8.1.执行ApplicationContextInitializer初始化方法

在容器准备前,先执行ApplicationContextInitializer接口的initialize()方法,该接口的子类在实例化SpringApplication时已经被实例化,具体怎么实例化的看1.1

  1. protected void applyInitializers(ConfigurableApplicationContext context) {
  2. // 循环执行AplicationContextInitializer接口的初始化方法initialize()方法
  3. for (ApplicationContextInitializer initializer : getInitializers()) {
  4. Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
  5. ApplicationContextInitializer.class);
  6. Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
  7. initializer.initialize(context);
  8. }
  9. }

2.8.2. 启动SpringApplicationRunListener.contextPrepared()

在执行完初始化方法后,执行SpringApplicationRunListener接口的contextPrepared()方法。

  1. @Override
  2. public void contextPrepared(ConfigurableApplicationContext context) {
  3. this.initialMulticaster
  4. .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
  5. }

2.8.3. 加载BeanDefinition

加载所有需要被创建的Bean信息,组装成BeanDefinition对象,这里不做分析。可以看Bean的配置文件加载源码分析

  1. protected void load(ApplicationContext context, Object[] sources) {
  2. if (logger.isDebugEnabled()) {
  3. logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
  4. }
  5. BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
  6. if (this.beanNameGenerator != null) {
  7. loader.setBeanNameGenerator(this.beanNameGenerator);
  8. }
  9. if (this.resourceLoader != null) {
  10. loader.setResourceLoader(this.resourceLoader);
  11. }
  12. if (this.environment != null) {
  13. loader.setEnvironment(this.environment);
  14. }
  15. loader.load();
  16. }

2.8.4. 启动SpringApplicationRunListener.contextLoaded()

在容器加载完成后,执行SpringApplicationRunListener接口的contextLoaded()方法。典型的实现类有EventPublishingRunListener

  1. void contextLoaded(ConfigurableApplicationContext context) {
  2. for (SpringApplicationRunListener listener : this.listeners) {
  3. listener.contextLoaded(context);
  4. }
  5. }

2.9. 刷新容器refreshContext()

刷新容器这部分内容是Spring 部分,这里不做详述

2.10. afterRefresh()

这是一个空方法,留给子类实现。在容器刷新完成后执行

2.11.启动SpringApplicationRunListener.started()

在容器刷新完成后,意味着SpringBoot已经启动完成,接下来会执行SpringApplicationRunListener接口的started()方法。

  1. void started(ConfigurableApplicationContext context) {
  2. for (SpringApplicationRunListener listener : this.listeners) {
  3. listener.started(context);
  4. }
  5. }

2.12.ApplicationRunner和CommandLineRunner的run()方法

执行ApplicationRunner和CommandLineRunner接口的run()方法,一般应用于在容器启动后,启动一些后台任务来做一些业务处理

  1. private void callRunners(ApplicationContext context, ApplicationArguments args) {
  2. List<Object> runners = new ArrayList<>();
  3. // 查找所有ApplicationRunner类型的Bean
  4. runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
  5. // 查找所有CommandLineRunner类型的Bean
  6. runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
  7. // 排序
  8. AnnotationAwareOrderComparator.sort(runners);
  9. for (Object runner : new LinkedHashSet<>(runners)) {
  10. // 执行ApplicationRunner接口的run()方法
  11. if (runner instanceof ApplicationRunner) {
  12. callRunner((ApplicationRunner) runner, args);
  13. }
  14. // 执行CommandLineRunner类型的run()方法
  15. if (runner instanceof CommandLineRunner) {
  16. callRunner((CommandLineRunner) runner, args);
  17. }
  18. }
  19. }

2.13.启动SpringApplicationRunListener.runing()方法

程序执行到这里,表示SpringBoot已经启动完成了,已经是一个正常启动的应用了。此时执行SpringApplicationRunListener接口的runing()方法。

  1. void running(ConfigurableApplicationContext context) {
  2. for (SpringApplicationRunListener listener : this.listeners) {
  3. listener.running(context);
  4. }
  5. }

3.启动失败异常处理

在SpringBoot启动失败时,会通过SpringBootExceptionReporter接口来处理启动的异常业务。我们可以实现该接口,在启动失败时来处理启动失败的异常。比如:发布启动失败事件等。

  1. private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
  2. Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) {
  3. try {
  4. try {
  5. handleExitCode(context, exception);
  6. // 执行SpringApplicationRunListener接口的failed()方法
  7. // 默认实现类EventPublishingRunListener
  8. if (listeners != null) {
  9. listeners.failed(context, exception);
  10. }
  11. }
  12. finally {
  13. reportFailure(exceptionReporters, exception);
  14. if (context != null) {
  15. context.close();
  16. }
  17. }
  18. }
  19. catch (Exception ex) {
  20. logger.warn("Unable to close ApplicationContext", ex);
  21. }
  22. ReflectionUtils.rethrowRuntimeException(exception);
  23. }

3.1 EventPublishingRunListener默认实现

在SpringBoot启动失败时,会执行SpringApplicationRunListener接口的failed()方法,这个接口的默认实现类EventPublishingRunListener中的failed()方法会发布ApplicationFailedEvent事件
EventPublishingRunListener的failed()方法

  1. public void failed(ConfigurableApplicationContext context, Throwable exception) {
  2. ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
  3. // 如果上下文容器此时已经激活,发布ApplicationFailedEvent事件
  4. if (context != null && context.isActive()) {
  5. // Listeners have been registered to the application context so we should
  6. // use it at this point if we can
  7. context.publishEvent(event);
  8. }
  9. else {
  10. // 容器没有激活,说明还没有向容器中添加监听器,此时需要向容器中添加监听器
  11. if (context instanceof AbstractApplicationContext) {
  12. // 向容器中添加监听器
  13. for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
  14. .getApplicationListeners()) {
  15. this.initialMulticaster.addApplicationListener(listener);
  16. }
  17. }
  18. // 事件发布失败时处理的Handler
  19. this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
  20. // 发布ApplicationFailedEvent事件
  21. this.initialMulticaster.multicastEvent(event);
  22. }
  23. }