Spring Boot与Spring MVC集成启动过程源码分析

  • 时间:
  • 浏览:1

亲们可不用还里能看过其调用host.addChild(context)将context加入host作为host的子容器,否则

其中8)查找所有ServletContextInitializer实现并合并为有另1个数组,否则 调用9)configureContext土办法,亲们来看一下:

这块Spring Boot根据@ConditionalOnClass判断当前运行时环境是是否是符合条件,即饱含了tomcat的jar包,机会满足则创建TomcatServletWebServerFactory的Bean实例加入spring容器管理,后边有用。

从SpringApplication.run说起:

土办法定义如下

WebApplicationType.deduceFromClasspath()用来自动识别这一值,看下实现:

可不用还里能看过,其像spring容器注册了DispatcherServletRegistrationBean的Bean实例,看一下它的继承关系:



其父类ServletRegistrationBean类有如下土办法:

时候亲们思考过,这肩头spring-boot到底做了那此使亲们的工作没人 简单,它如可将spring、spring-mvc、tomcat整合到同時 的呢?接下来亲们以项目启动深度图来分析整个初始化过程。

至此所有集成完毕,启动过程交给tomcat完成。

10)创建了TomcatStarter对象,并将starter加入context的conainerInitializer列表,见11),时候在tomcat的容器启动过程中就会调用到这一TomcatStarter实例。

亲们来看下TomcatStarter做了那此

看看new ServletContextInitializerBeans(getBeanFactory())做了那此

其中@Import每种引入了ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,深入看一下

实际上,这里亲们的调用机会到了spring-context包,确实 跟spring-boot机会没啥关系了,这确实 好多好多 有另1个标准的SpringApplicationContext的标准启动过程中refresh()每种,亲们全是对spring启动过程分解,好多好多 亲们只关注与tomcat,spring-mvc结合的每种。

直接看3)onRefresh()土办法,机会AnnotationConfigServletWebServerApplicationContext是ServletWebServerApplicationContext的子类,好多好多 流程进入ServletWebServerApplicationContext的onRefresh()土办法

@FunctionalInterface是java8中lambda支持的五种函数式接口selfInitialize这段逻辑在后边过程当中会被调用。

继续看6)中this.webServer = factory.getWebServer(...),亲们看下实现:

Pepper Metrics是我与同事开发的有另1个开源工具(https://github.com/zrbcool/pepper-metrics),其通过收集jedis/mybatis/httpservlet/dubbo/motan的运行性能统计,并暴露成prometheus等主流时序数据库兼容数据,通过grafana展示趋势。其插件化的架构也非常方便使用者扩展并集成否则 开源组件。

请亲们给个star,同時 欢迎亲们成为开发者提交PR同時 完善项目。

可不用还里能看过其对getServletContextInitializerBeans()的每个ServletContextInitializer均调用了onStartup土办法

可不用还里能看过这一4)createWebServer(),是亲们的关键

可不用还里能看过在后边创建了Tomcat实例作为webServer的内部管理实现,否则 向Tomcat的Service容器注入Connector,否则 设置默认Host容器的AutoDeploy属性及否则 的Tomcat初始化工作,最重要的一行是7)

亲们来看一下:

PS:下面代码分析过程中,着重于流程的串接,调用到某个变量时,作者会直接给出这一变量的具体实现,读者你说会产生困惑,否则 不须停下来,先想当然的按照作者的思路把流程捋完,后边会针对各个主要的变量初始化及选折 实现的过程进行逐个解释。

亲们来分解下这一run土办法

先看1)context = createApplicationContext()

负责创建spring主容器,这一土办法内部管理是根据具体项目运行时依赖的类来动态选折 实现的,机会是web项目则会选折 AnnotationConfigServletWebServerApplicationContext,至于选折 的规则及意味着着,这里先忽略,后边会专门介绍(旧时光门:ServletWebServerApplicationContext)。

接下来亲们重点看2)refreshContext(context)土办法

其土办法内部管理最终调用了((AbstractApplicationContext) applicationContext).refresh()土办法,亲们把这一土办法展开

可不用还里能看过TomcatStarter大约 hook了context启动的事件,否则 调用所有注入的initializers的onStartup土办法,似曾相识是吗?这好多好多 前面说的@FunctionalInterface函数接口,接下来亲们就深入看下前面提到的那个initializer的onStartup的具体内容

看看实现

spring-boot-autoconfigure/META-INF/spring.factories饱含一段配置:

其中:

5)ServletWebServerFactory factory = getWebServerFactory();

后边这句获取到的具体实现是TomcatServletWebServerFactory(旧时光门:TomcatServletWebServerFactory)

6)this.webServer = factory.getWebServer(getSelfInitializer());

先看6)中的getSelfInitializer()土办法:

可不用还里能看过它是通过判断classloader中与是是否是Servlet相关的class来判断的,好多好多 是运行时判断的。

否则 亲们来看下ServletWebServerFactoryAutoConfiguration类

addRegistration土办法又是有另1个模板土办法,实现好多好多 前面ServletRegistrationBean的addRegistration实现,而onStartup土办法会在SpringApplication.run()土办法的流程中被调用到,讲主流程的时候机会讲到,这里不再赘述

时候就将DispatchServlet与Tomcat进行了集成,DispatchServlet使用模板土办法设计模式,将具体的请求分配给不同的handler处理,这一后边会讲到,本篇就主要专注在Spring Boot与Spring MVC及Tomcat的集成原理每种。

register土办法是有另1个模板土办法,调用子类DynamicRegistrationBean的实现

这块有点意思,返回的是有另1个this::selfInitialize,土办法定义是返回org.springframework.boot.web.servlet.ServletContextInitializer,亲们看下它是那此定义

亲们知道,用spring-boot写有另1个web项目非常容易,pom继承spring-boot-parent否则 引入依赖spring-boot-starter-web,再写有另1个时候的主启动类,否则 就可不用还里能去写Controller了,十分简单,就像时候:

实际启动时,启动的是其子类AnnotationConfigServletWebServerApplicationContext,亲们来看下SpringApplication类,实际上SpringApplication在运行时根据情形决定使用哪种ApplicationContext



查看createApplicationContext()土办法



没人 这一this.webApplicationType又是哪来的值呢?

亲们看下这一构造土办法

其调用了ServletContext.addServlet土办法将DispatchServlet加入到Servlet容器,这是Servlet3.0中注册servlet的土办法。

没人 你你说会问,addRegistration又是那此时机调用的呢?

根据继承关系,查看其父类的父类RegistrationBean,其有另1个

DispatcherServletRegistrationBean是保证亲们的DispatcherServlet被注入到Servlet容器并生效的关键,亲们来看下它是如可初始化的

spring-boot-autoconfigure/META-INF/spring.factories饱含一段配置:

可不用还里能看过其从beanFactory中获取spring容器中所有的ServletContextInitializer实现,这里关于集成的每种在ServletRegistrationBean中,ServletRegistrationBean的注入过程参考:旧时光门:Dispatcherservletregistrationbean

否则 流程就顺了,亲们会调用到ServletRegistrationBean的onStartup土办法,最终会调用到servletContext.addServlet的Servlet3.0的标准将DispatchServlet注入到servlet容器中拦截所有的请求。

见下面代码: