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

  • 时间:
  • 浏览:4
  • 来源:大发5分6合_大发5分6合官网

其中:

5)ServletWebServerFactory factory = getWebServerFactory();

上方这句获取到的具体实现是TomcatServletWebServerFactory(时光图片 门:TomcatServletWebServerFactory)

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

先看6)中的getSelfInitializer()法子:

可是我亲戚亲戚许多人思考过,这肩头spring-boot到底做了什么使亲戚亲戚许多人的工作这么 简单,它怎样将spring、spring-mvc、tomcat整合到并肩的呢?接下来亲戚亲戚许多人以项目启动深度1来分析整个初始化过程。

都需要看后TomcatStarter相当于hook了context启动的事件,有日后调用所有注入的initializers的onStartup法子,似曾相识是吗?这可是我前面说的@FunctionalInterface函数接口,接下来亲戚亲戚许多人就深入看下前面提到的那个initializer的onStartup的具体内容

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

请亲戚亲戚许多人给个star,并肩欢迎亲戚亲戚许多人成为开发者提交PR并肩完善项目。

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

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

亲戚亲戚许多人来看下TomcatStarter做了什么

这块有点痛 意思,返回的是另另一好几个 多this::selfInitialize,法子定义是返回org.springframework.boot.web.servlet.ServletContextInitializer,亲戚亲戚许多人看下它是什么定义

DispatcherServletRegistrationBean是保证亲戚亲戚许多人的DispatcherServlet被注入到Servlet容器并生效的关键,亲戚亲戚许多人来看下它是怎样初始化的

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

实际上,这里亲戚亲戚许多人的调用有日后到了spring-context包,虽然跟spring-boot有日后没啥关系了,这虽然可是我另另一好几个 多标准的SpringApplicationContext的标准启动过程中refresh()部分,亲戚亲戚许多人就有对spring启动过程分解,太多太多亲戚亲戚许多人只关注与tomcat,spring-mvc结合的部分。

直接看3)onRefresh()法子,有日后AnnotationConfigServletWebServerApplicationContext是ServletWebServerApplicationContext的子类,太多太多流程进入ServletWebServerApplicationContext的onRefresh()法子

addRegistration法子又是另另一好几个 多模板法子,实现可是我前面ServletRegistrationBean的addRegistration实现,而onStartup法子会在SpringApplication.run()法子的流程中被调用到,讲主流程的日后有日后讲到,这里不再赘述

可是我就将DispatchServlet与Tomcat进行了集成,DispatchServlet使用模板法子设计模式,将具体的请求分配给不同的handler处置,你你你这个 上方会讲到,本篇就主要专注在Spring Boot与Spring MVC及Tomcat的集成原理部分。

有日后流程就顺了,亲戚亲戚许多人会调用到ServletRegistrationBean的onStartup法子,最终会调用到servletContext.addServlet的Servlet3.0的标准将DispatchServlet注入到servlet容器中拦截所有的请求。

见下面代码:

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

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

这么 你亲戚许多人说会问,addRegistration又是什么时机调用的呢?

根据继承关系,查看其父类的父类RegistrationBean,其另另一好几个 多多

看看实现

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

亲戚亲戚许多人知道,用spring-boot写另另一好几个 多web项目非常容易,pom继承spring-boot-parent有日后引入依赖spring-boot-starter-web,再写另另一好几个 多可是我的主启动类,有日后就都需要去写Controller了,十分简单,就像可是我:

register法子是另另一好几个 多模板法子,调用子类DynamicRegistrationBean的实现

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

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

都需要看后其从beanFactory中获取spring容器中所有的ServletContextInitializer实现,这里关于集成的部分在ServletRegistrationBean中,ServletRegistrationBean的注入过程参考:时光图片 门:Dispatcherservletregistrationbean

都需要看后在上方创建了Tomcat实例作为webServer的内部人员实现,有日后向Tomcat的Service容器注入Connector,有日后设置默认Host容器的AutoDeploy属性及你你你这个的Tomcat初始化工作,最重要的一行是7)

亲戚亲戚许多人来看一下:

都需要看后,其像spring容器注册了DispatcherServletRegistrationBean的Bean实例,看一下它的继承关系:



其父类ServletRegistrationBean类有如下法子:

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

继续看6)中this.webServer = factory.getWebServer(...),亲戚亲戚许多人看下实现:

亲戚亲戚许多人都需要看后其调用host.addChild(context)将context加入host作为host的子容器,有日后

其中8)查找所有ServletContextInitializer实现并合并为另另一好几个 多数组,有日后调用9)configureContext法子,亲戚亲戚许多人来看一下:

亲戚亲戚许多人来分解下你你你这个 run法子

先看1)context = createApplicationContext()

负责创建spring主容器,你你你这个 法子内部人员是根据具体项目运行时依赖的类来动态选择实现的,有日后是web项目则会选择AnnotationConfigServletWebServerApplicationContext,至于选择的规则及意味着着,这里先忽略,上方会专门介绍(时光图片 门:ServletWebServerApplicationContext)。

接下来亲戚亲戚许多人重点看2)refreshContext(context)法子

其法子内部人员最终调用了((AbstractApplicationContext) applicationContext).refresh()法子,亲戚亲戚许多人把你你你这个 法子展开

都需要看后其对getServletContextInitializerBeans()的每个ServletContextInitializer均调用了onStartup法子

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

实际启动时,启动的是其子类AnnotationConfigServletWebServerApplicationContext,亲戚亲戚许多人来看下SpringApplication类,实际上SpringApplication在运行时根据具体情况决定使用哪种ApplicationContext



查看createApplicationContext()法子



这么 你你你这个 this.webApplicationType又是哪来的值呢?

亲戚亲戚许多人看下你你你这个 构造法子

都需要看后它是通过判断classloader中是是否是有Servlet相关的class来判断的,太多太多是运行时判断的。

看看new ServletContextInitializerBeans(getBeanFactory())做了什么

从SpringApplication.run说起:

法子定义如下

都需要看后你你你这个 4)createWebServer(),是亲戚亲戚许多人的关键

有日后亲戚亲戚许多人来看下ServletWebServerFactoryAutoConfiguration类