springboot启动过程解析

2022-04-05 20:35:32 浏览数 (1)

虽然golang开始在后台开发横行,但是springboot还是目前大多数企业使用的技术栈。由于其成熟性,丰富的组件以及生态环境,是很多公司的首选。学习springboot需要了解其启动过程,对原理的理解可以避免停留在CRUD层面,对底层有很多深入的理解可以助力我们成长,解决深层次问题。

  1. 先看一下个简单的demo, 通过ideal创建的工程就会自动生成。
代码语言:javascript复制
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

2.SpringApplication构造函数

代码语言:javascript复制
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类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
  // 创建ApplicationContextInitializer并初始化
   this.bootstrapRegistryInitializers = new ArrayList<>(
         getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  // ApplicationListener 初始化
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  // 运行的主类
   this.mainApplicationClass = deduceMainApplicationClass();
}

3.run函数

代码语言:javascript复制
public ConfigurableApplicationContext run(String... args) {
   long startTime = System.nanoTime();
  // 类加载上线文
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
   configureHeadlessProperty();
  // 获取构造函数中创建的listener
   SpringApplicationRunListeners listeners = getRunListeners(args);
  // 开始监听
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
     //参数承载类
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
     //配置环境
     ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      configureIgnoreBeanInfo(environment);
     // 打印banner
      Banner printedBanner = printBanner(environment);
     //创建主的Bean
      context = createApplicationContext();
      context.setApplicationStartup(this.applicationStartup);
     //初始化工作
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
     //刷新
     refreshContext(context);
      afterRefresh(context, applicationArguments);
      Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
      }
      // 初始化监听完成
      listeners.started(context, timeTakenToStartup);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, listeners);
      throw new IllegalStateException(ex);
   }
   try {
      Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
      //进入准备阶段
      listeners.ready(context, timeTakenToReady);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

4.prepareContext 资源加载,并且初始化。

代码语言:javascript复制
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<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
  //加载初始化bean,IOC的实现
   load(context, sources.toArray(new Object[0]));
   listeners.contextLoaded(context);
}

5.refresh ioc的最后一步,对bean进行后续处理。

代码语言:javascript复制
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      //准备context用于刷新
      prepareRefresh();
     
      //通知子类刷新bean
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 准备beanfactory
      prepareBeanFactory(beanFactory);

      try {
         // 允许beanfactory刷新子类
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // 把bean注册到context中
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册processor用于bean的创建
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

         // 初始化资源信息
         initMessageSource();

         //广播信息初始化
         initApplicationEventMulticaster();

         //对特殊的子类进行刷新
         onRefresh();

         //检查注册的bean并且监听
         registerListeners();

         //初始化其他类懒加载的实力
         finishBeanFactoryInitialization(beanFactory);

         // 发布刷新完毕的消息
         finishRefresh();
      }

0 人点赞