启动流程

  1. 创建SpringApplication
SpringApplication.run(DemoApplication.class, args);

这是主程序的入口,该代码会运行以下方法:

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    // 先创建SpringApplication来引导程序的运行,然后执行run()方法
   return new SpringApplication(primarySources).run(args);
}

1.1 new SpringApplication(primarySources)

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 判断是不是web应用,如果是web应用的话就SERVLET枚举:应用程序应该作为基于servlet的web应用程序运行,并且应该启动嵌入式servlet web服务器。
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 设置初始化器。也就是创建ApplicationContextInitializer接口的实现类的对象并获取过来存到this.initializers集合中
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 设置监听器。
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 决定哪个类是主程序入口类。运行SpringApplication时是可以传入多个类的
   this.mainApplicationClass = deduceMainApplicationClass();
}

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

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    // 该方法调用下面的getSpringFactoriesInstances()方法
   return getSpringFactoriesInstances(type, new Class<?>[] {});
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取类加载器
   ClassLoader classLoader = getClassLoader();
    // 使用名称并确保唯一,防止重复。声明Set集合
    // 从META-INF/spring.factories中获取ApplicationContextInitializer配置下的所有name
   Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 创建Spring工厂实例
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 对ApplicationContextInitializer接口的实现对象进行排序
   AnnotationAwareOrderComparator.sort(instances);
    // 返回存储着ApplicationContextInitializer接口的实现对象的List
   return instances;
}

1.1.1.1 createSpringFactoriesInstances(, parameterTypes, classLoader, args, names)

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
      ClassLoader classLoader, Object[] args, Set<String> names) {
    // 创建List集合并设置大小
   List<T> instances = new ArrayList<>(names.size());
   for (String name : names) {
      try {
          // 通过反射创建每一个ApplicationContextInitializer接口实现类的对象
         Class<?> instanceClass = ClassUtils.forName(name, classLoader);
         Assert.isAssignable(type, instanceClass);
         Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
         T instance = (T) BeanUtils.instantiateClass(constructor, args);
          // 将创建出来的对象存进List集合中
         instances.add(instance);
      }
      catch (Throwable ex) {
         throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
      }
   }
   return instances;
}

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

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    // 该方法调用下面的getSpringFactoriesInstances()方法
   return getSpringFactoriesInstances(type, new Class<?>[] {});
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
   ClassLoader classLoader = getClassLoader();
    // 获取类加载器
    // 使用名称并确保唯一,防止重复。声明Set集合
    // 从META-INF/spring.factories中获取ApplicationListener配置下的所有name
   Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 创建Spring工厂实例。通过反射创建每一个ApplicationListener接口实现类的对象
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 对ApplicationListener接口的实现对象进行排序
   AnnotationAwareOrderComparator.sort(instances);
    // 返回存储着ApplicationListener接口的实现对象的List
   return instances;
}

1.1.2 this.mainApplicationClass = deduceMainApplicationClass(); 决定主程序入口类

private Class<?> deduceMainApplicationClass() {
   try {
       // 获取堆栈跟踪类
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
      for (StackTraceElement stackTraceElement : stackTrace) {
          // 判断类是不是包含main方法,如果是,创建该类
         if ("main".equals(stackTraceElement.getMethodName())) {
            return Class.forName(stackTraceElement.getClassName());
         }
      }
   }
   catch (ClassNotFoundException ex) {
      // Swallow and continue
   }
   return null;
}
  1. 执行run()方法:执行SpringBoot程序,创建并刷新IOC容器
public ConfigurableApplicationContext run(String... args) {
    // 监听springboot启动对象
   StopWatch stopWatch = new StopWatch();
    // 开启计时器
   stopWatch.start();
    // 声明IOC容器
   ConfigurableApplicationContext context = null;
    // 声明错误报告集合
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    // 对headless对象进行配置(与awt应用有关)
   configureHeadlessProperty();
    // 获取SpringApplication.run()运行时的监听器。参考1.1.1的运行流程
   SpringApplicationRunListeners listeners = getRunListeners(args);
    // 调用所有的listener的starting()方法
   listeners.starting();
   try {
       // 获取到命令行参数,封装成一个ApplicationArguments对象
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       // 准备配置环境。
      ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
       // 配置忽略bean信息
      configureIgnoreBeanInfo(environment);
       // 打印Banner
      Banner printedBanner = printBanner(environment);
       // 创建IOC容器
      context = createApplicationContext();
       // 获取错误记录器,用来记录错误信息
      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
       // 配置IOC容器、打印Banner等
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
       /*
        刷新容器。
        扫描、创建、加载所有组件,并对组件进行配置等操作都在这里。
       */
      refreshContext(context);
       // 里面没有代码,猜测是让我们来自定义里面的代码
      afterRefresh(context, applicationArguments);
       // 停止计时器
      stopWatch.stop();
       // 对日志的打印等操作
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
      }
       // 调用所有的 ApplicationListener 中的 started() 方法
      listeners.started(context);
       /*
        ApplicationRunner
        CommandLineRunner
        
        在IOC容器中获取到 
         ApplicationRunner
         CommandLineRunner
        这两个类型的组件,然后存储到一个List集合中,判断他们是否是这两个类型的组件,如果是,则调用他们的 run() 方法。
       */
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
       // 调用所有的 ApplicationListener 中的 running() 方法
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
    // 返回IOC容器
   return context;
}

2.1 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 准备环境

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments) {
    // 创建环境
   ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 配置环境
   configureEnvironment(environment, applicationArguments.getSourceArgs());
   ConfigurationPropertySources.attach(environment);
    // 调用环境准备完成方法:调用所有的SpringApplicationRunListener中的environmentPrepared()方法
   listeners.environmentPrepared(environment);
    // 将环境environment绑定到SpringApplication应用(主程序入口类)中
   bindToSpringApplication(environment);
    // 判断是否是自定义的环境
   if (!this.isCustomEnvironment) {
      environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
            deduceEnvironmentClass());
   }
   ConfigurationPropertySources.attach(environment);
   return environment;
}

2.1.1 ConfigurableEnvironment environment = getOrCreateEnvironment(); 获取或者创建环境(Enviroment)

private ConfigurableEnvironment getOrCreateEnvironment() {
    // 如果已有环境,则使用已有环境
   if (this.environment != null) {
      return this.environment;
   }
    // 根据当前web应用类型来获取对应的环境
   switch (this.webApplicationType) {
           // 在1.1可以看到怎么获取的webApplicationType
   case SERVLET:
           // 如果是web应用,那么会创建该环境
      return new StandardServletEnvironment();
   case REACTIVE:
           // 如果不是web应用,那么会创建该环境
      return new StandardReactiveWebEnvironment();
   default:
      return new StandardEnvironment();
   }
}

2.1.2 configureEnvironment(environment, applicationArguments.getSourceArgs()); 配置环境

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
   if (this.addConversionService) {
       // 获取转换器实例
      ConversionService conversionService = ApplicationConversionService.getSharedInstance();
       // 在环境中使用上面获取的转换器实例设置转换器服务
      environment.setConversionService((ConfigurableConversionService) conversionService);
   }
    // 配置属性源:为springboot添加默认属性(如果有配置文件则不添加默认属性)和添加命令行属性(如果有的话)
   configurePropertySources(environment, args);
    // 配置profiles环境(如果有配置的话)
   configureProfiles(environment, args);
}

2.2 prepareContext(context, environment, listeners, applicationArguments, printedBanner); 准备上下文

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
      SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    // 将刚才创建的环境对象设置到IOC容器中
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
    /*
     配置应用初始化器:
     调用前面获取到的所有的 ApplicationContextInitializer 的 initialize() 方法
    */
   applyInitializers(context);
    // 调用前面获取到的所有的 ApplicationListener 的 contextPrepared() 方法
   listeners.contextPrepared(context);
    // 打印日志
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }
    // 添加引导特定的单例beans
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // 注册命令行单例到beanFactory中
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    // 将Banner注册到beanFactory中
   if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
   }
    // 加载资源:获取到了主程序全限定 类名
   Set<Object> sources = getAllSources();
    // 断言
   Assert.notEmpty(sources, "Sources must not be empty");
    // 将主程序加载到IOC容器中
   load(context, sources.toArray(new Object[0]));
    // 调用前面创建的所有的 ApplicationListener 的 contextLoaded() 方法
   listeners.contextLoaded(context);
}