SpringBoot启动流程

SpringBoot启动流程

我们简单的先介绍一下SpringBoot的启动流程都需要哪些步骤
	1.加载配置文件
	2.准备上下文环境
	3.创建上下文对象
	4.启动spring
	5.启动tomcat

我们先来看一下springboot的启动流程图

SpringBoot启动流程

SpringBoot启动流程图


下面附上源码,我们从 SpringApplication.run(WebApplicaiton.class,args); 开始进入
找到SpringApplication下的run方法。在代码中都有注释标注,相信大家都可以看懂

public ConfigurableApplicationContext run(String... args) {
   long startTime = System.nanoTime();
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
   //设置了一个名为java.awt.headless的系统属性
   configureHeadlessProperty();
   //获取监听器 所有实现SpringApplicationRunListener这个接口的监听器
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //调用监听器里所有写的starting方法
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      //准备上下文的环境
      ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      configureIgnoreBeanInfo(environment);
      //启动的图标
      Banner printedBanner = printBanner(environment);
      //创建上下文的对象
      context = createApplicationContext();
      context.setApplicationStartup(this.applicationStartup);
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
      //进入到spring的容器方法
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
      }
      //调用了监听器的started方法
      listeners.started(context, timeTakenToStartup);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, listeners);
      throw new IllegalStateException(ex);
   }
   try {
       //计算springboot启动耗时
      Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
      //执行监听器的ready方法
      listeners.ready(context, timeTakenToReady);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

我们再走到prepareContext方法中

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
   applyInitializers(context);
   //设置完环境变量 监听器会调用的方法
   listeners.contextPrepared(context);
   bootstrapContext.close(context);
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }
   // Add boot specific singleton beans
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
      ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
      if (beanFactory instanceof DefaultListableBeanFactory) {
         ((DefaultListableBeanFactory) beanFactory)
               .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
      }
   }
   if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
   }
   // Load the sources
   Set sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   load(context, sources.toArray(new Object[0]));
   //调用监听器的contextLoaded方法
   listeners.contextLoaded(context);
}```
然后我们找到refreshContext方法

```java
	private void refreshContext(ConfigurableApplicationContext context) {
		if (this.registerShutdownHook) {
			shutdownHook.registerApplicationContext(context);
		}
		refresh(context);
	}

进入到ServletWebServerApplicationContext类下的refresh方法

@Override
public final void refresh() throws BeansException, IllegalStateException {
   try {
       //进入到了spring容器
      super.refresh();
   }
   catch (RuntimeException ex) {
      WebServer webServer = this.webServer;
      if (webServer != null) {
         webServer.stop();
      }
      throw ex;
   }
}

我会在之后的文章中更新在springboot启动的过程中是如何加载配置以及tomcat是如何启动的。相信大家在结合流程图看源码一定会很清晰的。。。。

页面更新:2024-05-04

标签:流程   监听器   上下文   流程图   容器   源码   加载   对象   环境   方法

1 2 3 4 5

上滑加载更多 ↓
Top