一、整体流程分析

  1. 使用构造方法 SpringApplication 初始化一些数据
    1. 初始化 webApplicationType,指定web类型,一般是servlet
    2. setInitializers 设置初始化类 ApplicationContextInitializer 到List
      1. 内部调用 getSpringFactoriesInstances 方法从 spring.factories 文件中获取 ApplicationContextInitializer下的所有类
    3. setListeners 设置监听器 ApplicationContextInitializer 到 List
      1. 内部调用 getSpringFactoriesInstances 方法从 spring.factories 文件中获取 ApplicationContextInitializer下的所有类
    4. Class._forName 加载主类启动器,即 _SpringBoot04Application.class
  2. 执行 SpringApplication().run() 中的run方法
    1. 设置启动时间、系统属性、环境参数、忽略bean的配置、banner、webApplicationType、异常报告器类型
    2. prepareContext 给应用上下文对象中设置一系列的属性值 (环境对象、初始化参数、发布监听事件、创建bean工厂)
    3. refreshContext 重写Spring的refresh方法,初始化bean的一些信息
    4. SpringApplicationRunListeners 启动
    5. callRunners �执行一些继承了 ApplicationRunner 和 CommandLineRunner 的方法
    6. SpringApplicationRunListeners 运行。

      二、源码剖析

      1、new SpringApplication(primarySources)

      1. public class SpringBoot04Application {
      2. public static void main(String[] args) {
      3. SpringApplication.run(SpringBoot04Application.class, args);
      4. }
      5. }
      进入run方法后如下
      1. public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
      2. return new SpringApplication(primarySources).run(args);
      3. }
      进入构造方法SpringApplication ```java List> initializers; List> listeners;

public SpringApplication(ResourceLoader resourceLoader, Class<?>… primarySources) {

  1. this.resourceLoader = resourceLoader;
  2. Assert.notNull(primarySources, "PrimarySources must not be null");
  3. // primarySources 就是 SpringBoot04Application
  4. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  5. // 决定用哪个 WebApplicationType,这里是 servlet
  6. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  7. // 实例化初始化类,这里初始化的是 spring.factories 文件里面的 ApplicationContextInitializer 下面的对象
  8. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  9. // 实例化监听器,这里初始化的是 spring.factories 文件里面的 ApplicationListener 下面的对象
  10. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  11. // 加载主类 即 SpringBoot04Application 到 JVN 内存中
  12. this.mainApplicationClass = deduceMainApplicationClass();
  13. }
  1. <a name="YhrjI"></a>
  2. ### 1.1 getSpringFactoriesInstances
  3. ```java
  4. // 这里的type就是 spring.factories 里面的等号左边的类名
  5. private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
  6. ClassLoader classLoader = getClassLoader();
  7. // Use names and ensure unique to protect against duplicates
  8. // 从 spring.factories 中读取 指定的type下的类名
  9. Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  10. // 根据全类名反射实例化 ctor.newInstance
  11. List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
  12. // 排序
  13. AnnotationAwareOrderComparator.sort(instances);
  14. return instances;
  15. }

1.1.1 SpringFactoriesLoader.loadFactoryNames

�从 spring.factories 中读取 指定的type下的类名

  1. public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
  2. String factoryTypeName = factoryType.getName();
  3. // loadSpringFactories 用于读取 spring.factories 所有的类名,并存如cache中
  4. // getOrDefault 获取指定的类名
  5. return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
  6. }

image.png

1.2 deduceMainApplicationClass

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

2、new SpringApplication(primarySources).run(args)

  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. // 设置一些系统属性
  7. configureHeadlessProperty();
  8. // 获取监听器:即在spring.factories中配置在 SpringApplicationRunListener 里的类(实现了接口SpringApplicationRunListener)
  9. SpringApplicationRunListeners listeners = getRunListeners(args);
  10. listeners.starting();
  11. try {
  12. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  13. // 提前准备一些环境参数
  14. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  15. // 读取需要忽略bean的配置
  16. configureIgnoreBeanInfo(environment);
  17. // 读取banner信息
  18. Banner printedBanner = printBanner(environment);
  19. // 根据 webApplicationType 创建对应的 加载并实例化对应的上下文对象(AnnotationConfigServletWebServerApplicationContext)
  20. context = createApplicationContext();
  21. // 获取 spring.factories 文件里面的 SpringBootExceptionReporter 下面的对象
  22. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
  23. new Class[] { ConfigurableApplicationContext.class }, context);
  24. // 上下文对象中设置一系列的属性值
  25. prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  26. // 内部调用 Spring 的refresh 方法,与Spring整合
  27. refreshContext(context);
  28. afterRefresh(context, applicationArguments);
  29. stopWatch.stop();
  30. if (this.logStartupInfo) {
  31. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
  32. }
  33. // 监听器执行
  34. listeners.started(context);
  35. // 执行一些继承了 ApplicationRunner 和 CommandLineRunner 的方法
  36. callRunners(context, applicationArguments);
  37. }
  38. catch (Throwable ex) {
  39. handleRunFailure(context, ex, exceptionReporters, listeners);
  40. throw new IllegalStateException(ex);
  41. }
  42. try {
  43. // Springboot启动
  44. listeners.running(context);
  45. }
  46. catch (Throwable ex) {
  47. handleRunFailure(context, ex, exceptionReporters, null);
  48. throw new IllegalStateException(ex);
  49. }
  50. return context;
  51. }

2.1 prepareContext

上下文对象中设置一系列的属性值 (环境对象、初始化参数、发布监听事件、创建bean工厂)

  1. private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
  2. SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
  3. context.setEnvironment(environment);
  4. // 添加一些 post processing 到 context 中
  5. postProcessApplicationContext(context);
  6. // 在所有的初始化器中添加 context(initializer.initialize(context);)
  7. applyInitializers(context);
  8. // 在所有的监听器中添加 context到对应的事件中 (listener.contextPrepared(context);)
  9. listeners.contextPrepared(context);
  10. if (this.logStartupInfo) {
  11. logStartupInfo(context.getParent() == null);
  12. logStartupProfileInfo(context);
  13. }
  14. // Add boot specific singleton beans
  15. // 获取spring的bean工厂,这里默认是DefaultListableBeanFactory
  16. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  17. beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  18. // beanFactory 的一些信息的设置
  19. if (printedBanner != null) {
  20. beanFactory.registerSingleton("springBootBanner", printedBanner);
  21. }
  22. if (beanFactory instanceof DefaultListableBeanFactory) {
  23. ((DefaultListableBeanFactory) beanFactory)
  24. .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  25. }
  26. if (this.lazyInitialization) {
  27. context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  28. }
  29. // Load the sources
  30. Set<Object> sources = getAllSources();
  31. Assert.notEmpty(sources, "Sources must not be empty");
  32. // 如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中
  33. load(context, sources.toArray(new Object[0]));
  34. // 监听器,发布事件 (listeners.contextLoaded(context))
  35. listeners.contextLoaded(context);
  36. }

2.1.1 load

如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中,即将类添加到BeanFactory中,这里就是将主类添加到BeanFactory

  1. private final AnnotatedBeanDefinitionReader annotatedReader;
  2. // Load beans into the application context.
  3. private int load(Class<?> source) {
  4. if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
  5. // Any GroovyLoaders added in beans{} DSL can contribute beans here
  6. GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
  7. load(loader);
  8. }
  9. if (isComponent(source)) {
  10. // 如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中
  11. this.annotatedReader.register(source);
  12. return 1;
  13. }
  14. return 0;
  15. }

2.2 refreshContext

内部调用了 Spring的refresh方法。Spring内部的refresh方法,这里不做过多介绍,具体参回顾:
5、Spring IOC 容器和对象的创建流程

1、prepareRefresh

�设置一些标志位、集合、时间等

2、obtainFreshBeanFactory

在Spring中,这个方法会创建一个默认的BeanFactory,但是在Springboot中,由于 prepareContext中已经创建了BeanFactory了,所以这里拿到的是Springboot创建的BeanFactory。

3、prepareBeanFactory

�工厂属性的设置工作

4、postProcessBeanFactory

�在beanFactory中设置一些SpringBoot相关的BeanPostProcessor(addBeanPostProcessor)
Spring里面的这个方法是空的

5、invokeBeanFactoryPostProcessors

执行 BeanFactoryPostProcessors,即 实现了接口 BeanFactoryPostProcessor 的一些类。

6、registerBeanPostProcessors

注册 BeanPostProcessors 相关内容( 实现了 接口 BeanPostProcessors 的一些方法),添加到beanFactory中—》beanFactory.addBeanPostProcessor

7、�initMessageSource()

为上下文初始化 message原,即不同语言的消息体,国际化操作。

8、initApplicationEventMulticaster()

初始化事件监听多路广播器
onRefresh();留给子类初始化其他的bean
�registerListeners();在所有注册的bean中查找listener bean,注册到消息广播器中。

9、onRefresh

Spring里面的这个方法是空的
Springboot 在这里创建Tomcat

  1. @Override
  2. protected void onRefresh() {
  3. super.onRefresh();
  4. try {
  5. createWebServer();
  6. }
  7. catch (Throwable ex) {
  8. throw new ApplicationContextException("Unable to start web server", ex);
  9. }
  10. }

10、registerListeners

在所有注册的bean(即实现了接口 ApplicationListener 的一些方法)中查找listener bean,注册到消息广播器中

11、finishBeanFactoryInitialization

通过 方法 finishBeanFactoryInitialization() 初始化所有非懒加载的单例对象。

2.3 callRunners

�执行一些继承了 ApplicationRunner 和 CommandLineRunner 的方法

2.4 listeners.running(context)

启动Spring.factories中的方法(org.springframework.boot.SpringApplicationRunListener下的一些方法)