spring-boot-mvc启动流程

本文详细探讨了Spring Boot MVC应用程序的启动流程,从容器类型确定、创建web容器、启动内嵌Tomcat到DispatcherServlet的初始化。核心步骤包括:WebApplicationType枚举决定容器类型、ServletWebServerApplicationContext创建、Tomcat启动以及DispatcherServlet的onRefresh方法。通过跟踪源码,揭示了从创建到启动的每个关键环节。
摘要由CSDN通过智能技术生成

spring-boot-mvc启动流程

1、前言

在web应用开发中,我们比较常用的是spring boot+spring mvc的组合。该组合的核心点就是内嵌tomcat和mvc的dispatcherServlet,今天,我们就来探究一下其启动流程。

前置知识点:spring boot原理、spring mvc原理

源码版本:spring boot 2.1.7

2、流程

此处先给出结论,抓住主线,便于后面的学习。

核心步骤分四步:

  • 容器类型确定
  • 创建web容器
  • 启动内嵌tomcat
  • 启动DispatcherServlet

大致时序图如下:

image-20210401165418890

3、容器类型

容器类型,由WebApplicationType枚举类定义:

  • web容器

    • mvc容器
    • reactive容器
  • 非web容器

SpringApplication的构造方法中设置

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
   this.resourceLoader = resourceLoader;
  。。。。
   //调用方法设置容器类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   。。。。
   this.mainApplicationClass = deduceMainApplicationClass();
}

WebApplicationType.deduceFromClasspath()获取容器类型

static WebApplicationType deduceFromClasspath() {
   
   if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
   
       //reactive
      return WebApplicationType.REACTIVE;
   }
   for (String className : SERVLET_INDICATOR_CLASSES) {
   
      if (!ClassUtils.isPresent(className, null)) {
   
          //普通容器
         return WebApplicationType.NONE;
      }
   }
    //返回servlet容器,即mvc
   return WebApplicationType.SERVLET;
}
  • WebApplicationType.REACTIVE - 当类路径中存在REACTIVE_WEB_ENVIRONMENT_CLASS并且不存在MVC_WEB_ENVIRONMENT_CLASS时
  • WebApplicationType.NONE - 也就是非Web型应用(Standard型),此时类路径中不包含WEB_ENVIRONMENT_CLASSES中定义的任何一个类时
  • WebApplicationType.SERVLET - 类路径中包含了WEB_ENVIRONMENT_CLASSES中定义的所有类型时

4、创建web容器

在上步,我们已经确定了容器的类型,接下来就是创建容器了。核心步骤:

  • 根据类型获取定义的Class
  • 通过反射创建容器

源码如下:

**SpringApplication.run()方法中的createApplicationContext()**执行

public ConfigurableApplicationContext run(String... args) {
   
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
	...
   try {
   
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       //准备环境,确认activefile,确认配置的文件的内容全部可用,此处会准备bootstarpapplication,
      ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  .	  ...
      //创建容器
      context = createApplicationContext();
     ...
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
      //刷新容器,关键点,tomcat在这里面的onrefresh中创建
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
 	 ...
   return context;
}

createApplicationContext()方法。根据容器类型创建容器,mvc的容器为ServletWebServerApplicationContext

protected ConfigurableApplicationContext createApplicationContext() {
    
   Class<?> contextClass = this.applicationContextClass;
    //根据容器type加载class
   if (contextClass == null) {
   
      try {
   
         switch (this.webApplicationType) {
   
         case SERVLET:
             //需要的servletWeb容器的Class,mvc
            contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
            break;
         case REACTIVE:
            contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
            break;
         default:
            contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
         }
      }
      catch (ClassNotFoundException ex) {
   
         ...
      }
   }
    //根据class创建并返回web容器
   return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

5、 启动tomcat

我们观察项目启动的日志,会有tomcat的相关日志。debug找到相关的类,便于确定调用堆栈。

Debug的调用堆栈如下:

我们跟着调用堆栈走,先看看onRefrensh()方法。

5.1、onRefresh

ServletWebServerApplicationContext实现了o

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值