首页 > 编程语言 >深入源码:Spring Boot 内置 Tomcat 的实现机制分析

深入源码:Spring Boot 内置 Tomcat 的实现机制分析

时间:2024-12-10 14:00:01浏览次数:6  
标签:Tomcat Spring start 源码 组件 方法

  在本文章中,我们将从源码层面深入分析 Spring Boot 如何实现内置 Tomcat 的功能。通过对相关代码的剖析,我们将揭示内置 Tomcat 的工作原理以及其在 Spring Boot 应用中的集成方式。这一过程不仅有助于理解 Spring Boot 的设计思路,还能为开发者在实际应用中提供更深入的见解。

  在深入分析 Spring Boot 内置 Tomcat 之前,我们首先需要全面了解 Tomcat 的组成结构。它是我们能够看懂源码的关键。

1.Tomcat的组成

  Apache Tomcat 是一个开源的 Java Servlet 容器和 Web 服务器,广泛用于运行 Java 应用程序。它的核心组件包括:

  1. Connector:负责处理客户端请求和服务器响应的组件,支持多种协议(如 HTTP 和 AJP)。Connector 将接收到的请求传递给相应的 Servlet,并将 Servlet 生成的响应返回给客户端。

  2. Container:Tomcat 的核心部分,包含了用于管理 Servlet 和 JSP 的各类组件。Container 进一步分为:

    • Engine:负责处理请求的主要组件,通常包含一个或多个 Host。
    • Host:对应一个虚拟主机,负责管理一组 Web 应用。
    • Context:表示一个特定的 Web 应用,负责管理与该应用相关的 Servlet、Filter 和 Listener。
    • Wrapper: Servlet在Tomcat中存在的形式,遵循生命周期,易于Tomcat的管理,可以将其直接看做servlet,其会和Context组件绑定父子关系。

  整体架构图如下:

2.Spring Boot内置Tomcat

  我们都知道,Spring Boot是在Spring MVC的基础上做了大量的自动配置来简化开发者的工作量,比较典型的就是自动装配和内置Tomcat,再之前的文章中我们也从源码层面探究了自动装配的原理,感兴趣的朋友可以去看一下:Spring Boot自动装配与自定义Bean优先级的源码解析之旅-CSDN博客 ,本篇文章就不再做过多介绍。接下来我们详细看一下内置Tomcat如何实现的。

  Spring Boot依托于Spring MVC,而Spring MVC又依托于Spring Framework,所以Spring Framework是两种架构的基础,而Spring Framework的源码核心即AbstractApplicationContext.refresh()方法,而该方法中给开发者预留了一个自定义扩展的内部方法即onRefresh()。Spring Boot正式利用该方法来实现了内置Tomcat。

再Spring Boot中自定义了AbstractApplicationContext(IOC容器的顶级父类)的实现类AnnotationConfigServletWebServerApplicationContext,其存在一个父类ServletWebServerApplicationContext,该父类中自定义了onRefresh()方法,其是我们内置Tomcat的开始,如下图:

  接着我们看一下createWebServer方法,具体如下:

  上图中比较重要的方法有三个,分别是getWebServerFactory、getWebServer、WebServerStartStopLifecycle,接下来我们分别看一下:

1.getWebServerFactory

   其主要作用是获取Web容器工厂创建相应的ServletWebServerFactory对象,具体源码如下:

  这个方法很简单,从容器中获取ServletWebServerFactory实现类,即Web容器工厂,重点是该容器工厂是何时创建,又是如何被放入IOC容器的。这就离不开Spring Boot的自动装配,其存在一个比较重要的自动配置类WebMvcAutoConfiguration,该配置类帮我们导入了一个DispatcherServletAutoConfiguration自动配置类,如下图:

  而DispatcherServletAutoConfiguration自动配置类又帮我们导入了一个ServletWebServerFactoryAutoConfiguration的配置类,如下图:

 ServletWebServerFactoryAutoConfiguration配置类则是我们初始化Web工厂的关键,它帮我们导入了4个核心配置类,分别是:

(1)ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class:帮我们注册一个WebServerFactoryCustomizerBeanPostProcessor后置处理器,当我们的容器工厂WebServerFactory初始化的时候,会调用容器中所有的WebServerFactoryCustomizer接口的实现类,调用其customizer.customize(webServerFactory)方法,给开发者一个自定义Web容器工厂的机会;

(2)ServletWebServerFactoryConfiguration.EmbeddedTomcat.class:创建Tomcat类型的Web容器工厂;

(3)ServletWebServerFactoryConfiguration.EmbeddedJetty.class:创建Jetty类型的Web容器工厂;

(4)ServletWebServerFactoryConfiguration.EmbeddedUndertow.class:创建Undertow类型的Web容器工厂。

具体源码如下:

  接着看一下EmbeddedTomcat.class,具体如下:

  经过上述自动配置类,我们需要的Web容器工厂就已经填充到IOC容器中,所以可以在getWebServerFactory方法中直接获取。

2.getWebServer(getSelfInitializer())

  这个方法比较重要,也是内置Tomcat的核心,其实现了容器(Tomcat)的创建、BaseDir的设置 、Server、Services、Connector等各组件的初始化和定制化等一系列操作。

其参数getSelfInitializer()是一个lambda,会调用ServletContextInitializer中的onStartup方法,将我们自动配置类DispatcherServletAutoConfiguration中初始化
的DispatcherServletRegistrationBean注册到servlet容器中,不过他的执行时机是在Tomcat启动之后Context组件start的时候通过spi机制将servlet封装成wrapper,同时将wrapper与context绑定父子关系。该方法本章不做过多介绍,感兴趣的客观可以看一下:深入源码解析:Spring Boot 如何加载 Servlet 、Filter 与 Listener-CSDN博客 。

  我们言归正传,接着看一下getWebServer方法,其源码如下:

  整个方法比较核心的是prepareContext(tomcat.getHost(), initializers)和getTomcatWebServer(tomcat)两个方法,接下来我们分别看一下:

1.prepareContext(tomcat.getHost(), initializers)

  该方法的核心是准备创建TomcatEmbeddedContext,每一个context组件对应一个webapp(项目),并将其通过host关联到tomcat。具体源码如下:

2.getTomcatWebServer(tomcat)

  实例化TomcatWebServer,将上面的各组件进行init和start过程,该过程中context组件start的时候会触发SCI将DispatcherServlet以及一些Filter添加到Tomcat context组件中。其底层调用的核心方法为initialize()方法,其源码如下:

  再上面图片中在context组件start过层中将connector组件从services组件中进行了剔除,避免其进行start方法,那么为什么不让它执行start方法呢?

  首先我们需要明确,connector组件是用来进行通信接受请求的,一旦其执行start方法,其底层的Endpoint组件下的acceptor和poller组件就开始正常工作接受前端请求,但是需要注意的是Spring Boot是通过实现onRefresh()来实现内嵌Tomcat的,而整个Spring源码bean对象的生成是在onRefresh()方法之后的,如果此时开始接受请求,而IOC容器中无任何bean对象,如何响应请求??所以将connector组件的start方法进行了后移。

  那么何时进行connector组件的start方法呢,这里就需要我们的WebServerStartStopLifecycle类。

3.WebServerStartStopLifecycle

   其作用就是在IOC容器启动完成后,执行WebServer的start方法来进行connector组件的start,从而正式接受请求。具体源码如下:

  再Spring源码的refresh方法的最后一步finishRefresh()方法中,会获取IOC容器中所有Lifecycle接口的实现类,执行其start()方法,具体如下:

  上图中的onRefresh()方法最终底层会调用startBeans(true)方法,具体源码如下:

  经过上面的流程,再Spring源码最后一步就会调用WebServerStartStopLifecycle.start()方法,具体如下:

  接下来我们就看一下start方法,具体源码如下:

  接着看一下addPreviouslyRemovedConnectors方法,具体如下:

  继续看一下addConnector方法,如下:

  至此connector组件就已经start完成,整个应用就开始接受请求。

  如果您希望更深入地学习SpringBoot源码,我强烈推荐您访问以下项目链接:https://gitee.com/chengyadong555/spring-boot.git 。在这个项目中,您将发现对SpringBoot源码的逐行分析,作者不仅提供了丰富的注释,还融入了自己独到的理解和见解。

标签:Tomcat,Spring,start,源码,组件,方法
From: https://blog.csdn.net/qq_26733517/article/details/144365660

相关文章

  • 深入源码解析:Spring Boot 如何加载 Servlet 、Filter 与 Listener
     我们知道,SpringBoot是在SpringMVC的基础上进行了封装,以简化开发者的工作量。尽管如此,SpringBoot的底层架构依然离不开SpringMVC的核心组件,如Servlet、Filter、Listener,以及RequestMappingHandlerMapping和RequestMappingHandlerAdapter等。 在传统的Spring......
  • 【Spring Boot 编程】Java SPI机制及其与Spring SPI、Spring Boot SPI的异同
    JavaSPI机制介绍JavaSPI(ServiceProviderInterface)是一种服务发现机制,广泛应用于Java平台的框架中,如Spring、Dubbo、JDBC等。JavaSPI允许在运行时动态地加载实现特定接口的类,而无需在代码中显式指定该类。这种机制的核心思想是通过接口定义服务,并允许外部实现类来提供具体的......
  • Java毕设项目:基于Springboot书籍图书租借租赁网站系统设计与实现开题报告
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩,提供核心代码讲解,答辩指导。项目配有对应开发......
  • 基于SpringBoot+Vue的茶叶商城系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • 基于SpringBoot+Vue的在线考试系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • 基于Spring Boot的干洗店预约洗衣系统
    目录前言功能设计系统实现相关代码为什么选择我?获取源码作者介绍:✌️大厂全栈码农|毕设实战开发,CSDN平台全栈领域优质创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。✌️博主主页:百成Java往期系列:SpringBoot、SSM、JavaWeb、python、小程序......
  • 基于HTML+CSS+JavaScript仿淘宝购物商城设计毕业论文源码
    常见网页设计作业题材有个人、美食、公司、学校、旅游、电商、宠物、电器、茶叶、家居、酒店、舞蹈、动漫、服装、体育、化妆品、物流、环保、书籍、婚纱、游戏、节日、戒烟、电影、摄影、文化、家乡、鲜花、礼品、汽车、其他等网页设计题......
  • web大学生个人网站作业模板——上海旅游景点介绍网页代码 家乡旅游网页制作模板 大学
    家乡旅游景点网页作业制作网页代码运用了DIV盒子的使用方法,如盒子的嵌套、浮动、margin、border、background等属性的使用,外部大盒子设定居中,内部左中右布局,下方横向浮动排列,大学学习的前端知识点和布局方式都有运用,CSS的代码量也很足、很细致,使用hover来完成过渡效果、鼠......
  • springboot湿地公园旅游信息管理系统-计算机毕业设计源码00658
     目录摘要1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.2系统流程分析2.2.1 数据流程3.3.2 业务流程2.3 系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4 系统用例分析2.5本章小结3 系......
  • springboot市社保局社保信息管理与分析系统-计算机毕业设计源码03479
     摘  要 社保是保障公民基本生活的重要制度。随着社保参保人数的增加和社保政策的不断调整,传统的手工操作已不能满足社保管理的需要。因此,设计和实现一个高效、安全、可靠的社保信息管理和分析系统对于有效管理和优化社保工作具有重要现实意义。市社保局社保信息管理与分......