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

  • 时间:
  • 浏览:0
  • 来源:uu快3概率_uu快3官网pk10_平台

看看实现

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



查看createApplicationContext()办法



如此一点this.webApplicationType又是哪来的值呢?

亲戚亲戚你们都 看下一点构造办法

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

需用看多其从beanFactory中获取spring容器中所有的ServletContextInitializer实现,这里关于集成的主次在ServletRegistrationBean中,ServletRegistrationBean的注入过程参考:光阴图片 门:Dispatcherservletregistrationbean

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

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

亲戚亲戚你们都 知道,用spring-boot写三个小多 web项目非常容易,pom继承spring-boot-parent而且 引入依赖spring-boot-starter-web,再写三个小多 然后的主启动类,而且 就需用去写Controller了,十分简单,就像然后:

需用看多在上方创建了Tomcat实例作为webServer的结构实现,而且 向Tomcat的Service容器注入Connector,而且 设置默认Host容器的AutoDeploy属性及一点的Tomcat初始化工作,最重要的一行是7)

亲戚亲戚你们都 来看一下:

需用看多其对getServletContextInitializerBeans()的每个ServletContextInitializer均调用了onStartup办法

PS:下面代码分析过程中,着重于流程的串接,调用到某个变量时,作者会直接给出一点变量的具体实现,读者跟我说会产生困惑,而且 何必 停下来,先想当然的按照作者的思路把流程捋完,上方会针对各个主要的变量初始化及确定实现的过程进行逐个解释。

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

而且 亲戚亲戚你们都 来看下ServletWebServerFactoryAutoConfiguration类

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

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

register办法是三个小多 模板办法,调用子类DynamicRegistrationBean的实现

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

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

然后亲戚亲戚你们都 思考过,这肩头spring-boot到底做了那此使亲戚亲戚你们都 的工作如此简单,它怎样将spring、spring-mvc、tomcat整合到同時 的呢?接下来亲戚亲戚你们都 以项目启动宽度来分析整个初始化过程。

亲戚亲戚你们都 需用看多其调用host.addChild(context)将context加入host作为host的子容器,而且

其中8)查找所有ServletContextInitializer实现并合并为三个小多 数组,而且 调用9)configureContext办法,亲戚亲戚你们都 来看一下:

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



其父类ServletRegistrationBean类有如下办法:

这块有点痛 意思,返回的是三个小多 this::selfInitialize,办法定义是返回org.springframework.boot.web.servlet.ServletContextInitializer,亲戚亲戚你们都 看下它是那此定义

addRegistration办法又是三个小多 模板办法,实现本来 前面ServletRegistrationBean的addRegistration实现,而onStartup办法会在SpringApplication.run()办法的流程中被调用到,讲主流程的然后可能讲到,这里不再赘述

然后就将DispatchServlet与Tomcat进行了集成,DispatchServlet使用模板办法设计模式,将具体的请求分配给不同的handler补救,一点上方会讲到,本篇就主要专注在Spring Boot与Spring MVC及Tomcat的集成原理主次。

其中:

5)ServletWebServerFactory factory = getWebServerFactory();

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

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

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

需用看多一点4)createWebServer(),是亲戚亲戚你们都 的关键

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

见下面代码:

实际上,这里亲戚亲戚你们都 的调用可能到了spring-context包,实在跟spring-boot可能没啥关系了,这实在本来 三个小多 标准的SpringApplicationContext的标准启动过程中refresh()主次,亲戚亲戚你们都 都有对spring启动过程分解,太少有亲戚亲戚你们都 只关注与tomcat,spring-mvc结合的主次。

直接看3)onRefresh()办法,可能AnnotationConfigServletWebServerApplicationContext是ServletWebServerApplicationContext的子类,太少有流程进入ServletWebServerApplicationContext的onRefresh()办法

亲戚亲戚你们都 来分解下一点run办法

先看1)context = createApplicationContext()

负责创建spring主容器,一点办法结构是根据具体项目运行时依赖的类来动态确定实现的,可能是web项目则会确定AnnotationConfigServletWebServerApplicationContext,至于确定的规则及意味着,这里先忽略,上方会专门介绍(光阴图片 门:ServletWebServerApplicationContext)。

接下来亲戚亲戚你们都 重点看2)refreshContext(context)办法

其办法结构最终调用了((AbstractApplicationContext) applicationContext).refresh()办法,亲戚亲戚你们都 把一点办法展开

从SpringApplication.run说起:

办法定义如下

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

亲戚亲戚你们都 来看下TomcatStarter做了那此

spring-boot-autoconfigure/META-INF/spring.factories中有 一段配置:

需用看多TomcatStarter要花费hook了context启动的事件,而且 调用所有注入的initializers的onStartup办法,似曾相识是吗?这本来 前面说的@FunctionalInterface函数接口,接下来亲戚亲戚你们都 就深入看下前面提到的那个initializer的onStartup的具体内容

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

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

如此你跟我说会问,addRegistration又是那此时机调用的呢?

根据继承关系,查看其父类的父类RegistrationBean,其有三个小多

需用看多它是通过判断classloader中是有无Servlet相关的class来判断的,太少有是运行时判断的。

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

spring-boot-autoconfigure/META-INF/spring.factories中有 一段配置: