启动项目
SpringBoot项目有一个主程序启动类,在主程序启动勒种有个启动项目main()方法,通过执行SpringApplication.run()启动整个SpringBoot程序
@SpringBootApplicationpublic class SpringbootDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootDemoApplication.class, args);}}
public static ConfigurableApplicationContext run(Class<?> primarySource,String... args) {return run(new Class[]{primarySource}, args);}public static ConfigurableApplicationContext run(Class<?>[] primarySources,String[] args) {return (new SpringApplication(primarySources)).run(args);}
从源码中可以看出来,SpringApplication.run()方法内部执行了两个操作,分别是SpringApplication实例的初始化和调用run()启动项目
SpringApplication实例的初始化
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");//把项目启动类.class设置为属性存储起来this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//判断当前webApplicationType应用的类型this.webApplicationType = WebApplicationType.deduceFromClasspath();//初始化器,最后会调用这些初始化器setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//设置监听器setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//用于推断并设置项目main()方法启动主程序启动类this.mainApplicationClass = deduceMainApplicationClass();}
从上诉源码中可以看出来,SpringApplication的初始化过程包括4部分
- this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
用于判断webApplicationType应用的类型。deduceFromClasspath()方法用于插手Classpath类路径下是否存在某个特征类,从而判断当前webApplicationType类似是SERVLETyingy (Spring5之前的传统MVC应用)还是REACTIVE应用(Spring5开始出现的WebFlux交互式应用)
- setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
用于SpringApplication应用的初始化器设置。在初始化器设置的过程中,会使用Spring类加载器SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationContextInitializer
- setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
用于SpringApplication应用的监听器设置。监听器设置的过程与上一步初始化器设置基本一样,也是使用SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationListener。
- this.mainApplicationClass = deduceMainApplicationClass();
项目初始化
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//第一步 获取并启动监听器SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//第二步 根据SpringApplicationRunListeners以及参数来准备环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);//第三步 创建Spring容器context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//第四步 容器前置处理prepareContext(context, environment, listeners, applicationArguments, printedBanner);//第五步 刷新容器refreshContext(context);//第六步 容器后置处理afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//第七步 发出结束执行的事件listeners.started(context);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}
SpringBoot执行流程图

