首页 > 编程语言 >深入源码解析:Spring Boot 如何加载 Servlet 、Filter 与 Listener

深入源码解析:Spring Boot 如何加载 Servlet 、Filter 与 Listener

时间:2024-12-10 13:59:45浏览次数:5  
标签:容器 Tomcat Spring Boot Listener 源码 组件 Servlet

  我们知道,Spring Boot 是在 Spring MVC 的基础上进行了封装,以简化开发者的工作量。尽管如此,Spring Boot 的底层架构依然离不开 Spring MVC 的核心组件,如 Servlet、Filter、Listener,以及RequestMappingHandlerMapping 和RequestMappingHandlerAdapter等。

  在传统的 Spring MVC项目中,我们可以通过web.xml文件、注解的方式,或通过 SPI 扩展机制来配置和初始化这些关键组件。然而,在 Spring Boot 项目中,我们默认是没有做这些操作的,那么其又是如何初始化这些关键组件呢?本帖我们着重探究Servlet、Filter、Listener。

  再探究Servlet、Filter、Listener初始化的过程前,我们需要了解两个概念,Web容器和Spring IOC容器,二者不是同一个概念。

  Web 容器(也称为 Servlet 容器)是用于处理 Web 应用程序的服务器环境。它负责管理 Web 应用程序的生命周期,并提供必要的服务来处理 HTTP 请求和响应,常见的 Web 容器有 Apache Tomcat、Jetty等。注意我们的Servlet、Filter、Listener组件就是存储在该容器中。

  Spring IOC 容器(Inversion of Control 容器)是 Spring 框架的核心部分,它负责管理 Java bean 对象的生命周期和依赖关系。

  从上面可以看出,Servlet、Filter、Listener的初始化离不开Web容器,而我们常用的就是Tomcat,再Spring Mvc中我们采用的外置Tomcat,但是再Spring Boot中采用了内置Tomcat,二者大同小异,所以再研究Spring Boot内置Tomcat如何初始化Servlet、Filter、Listener组件前,我们需要先大体了解一下Spring MVC外置Tomcat 如何加载这三个组件。

1.外置Tomcat

  外置Tomcat典型应用就是Spring MVC项目。首先我们需要先了解一下Tomcat的整体架构,如下图:

  注意:Spring IOC容器的创建是在上图中Context组件中执行servlert.init方法进行创建的,而Tomcat启动Spring MVC项目的时候,会按照server->service->Engine->host->context->wrapper(默认DispatcherServlet)的顺序进行对象的实例化,那么很明显我们的servlet是再Spring IOC容器创建之前就已经创建了,因此Spring IOC无法存储管理这些组件,所以用Web容器来存储管理这些组件。

  再外置Tomcat中,整个项目启动的时候会创建context实例(对应一个项目),而context实例的实现类为StandardContext,该类实现了Lifecycle接口,因此具有生命周期,再其生命周期中存在12中状态,每种状态均会发布不同的事件,其有一个非常重要的监听器即ContextConfig,该监听器针对context组件再不同的生命阶段发布的不同事件进行监听处理,其中就包括我们项目中web.xml的解析,这样就会帮我们创建三大组件,然后绑定到context组件中的属性中。如下图:

  通过上面流程,可以看出Servlet、Filter、Listener组件需要存储在Web容器中,且要和Tomcat中的context组件绑定对应的关系。

  但是再Spring Boot项目中,我们是通过内嵌Tomcat来实现项目的加载,而内嵌Tomcat的实现是再Spring源码中的refresh()方法中的onRefresh()方法来具体实现的,再执行onRefresh()方法之前Spring IOC容器就已经创建完成了,那么Spring Boot是如何实例化Servlet、Filter、Listener组件以及又是如何将这三个组件跟Web容器中的Context组件绑定关系呢?

2.内置Tomcat

  内置Tomcat的典型应用就是Spring Boot项目,而从Spring Boot的源码中可以看出,内嵌Tomcat的实现是在ServletWebServerApplicationContext中的onRefresh() 方法,但是该方法的调用比较靠后,此时Spring IOC容器已经创建而Web容器还未创建,那么Spring Boot项目是如何创建Servlet、Filter、Listener组件,又是如何将三大组件跟Web容器中的context绑定关系。

1.Spring Boot项目是如何创建Servlet、Filter、Listener

  Spring Boot再创建Servlet、Filter、Listener组件时原理相同,此处我们以Servlet为主进行介绍。Servlert的创建离不开Spring Boot的自动装配,而WebMvcAutoConfiguration自动配置类就显的比较重要,如下图:

  其会帮我们导入一个DispatcherServletAutoConfiguration,而该类则是DispatcherServlet创建的重中之重,如下图:

  经过上面Spring Boot的自动装配,默认的Servlet就已经注入到IOC容器中。

2.Spring Boot IOC容器中的servlet如何跟Web容器中的context绑定关系

  该过程是在内嵌Tomcat启动的过程中进行的,即Spring源码中的onRefresh() 方法中进行的。该流程的实现离不开一个关键类,即TomcatStarter,它实现了ServletContainerInitializer接口(jakarta.servlet),上面的DispatcherServletRegistrationBean也实现了ServletContainerInitializer接口(org.springframework.boot.web.servlet)。注意:两者只是名称相同,全类限定名不同哈。

  我们需要先看一下内嵌Tomcat是如何启动的,关键是ServletWebServerApplicationContext.createWebServer()方法,如下图:

  而真正实现Servlet与context组件绑定父子关系的是getWebServer(getSelfInitializer())方法的参数getSelfInitializer()方法,该方法是一个lambda,具体如下:

  我们接着看一下getWebServer方法,看看TomcatStart,如何被设置,如何被调用:

  接着看一下configureContext(context, initializersToUse)方法,如下:

  那么TomcatStarter又是何时被调用的,前面也说到了context的声明周期中存在多种状态,当该组件start的时候,会调用TomcatStarter,如下图:

 接下来看一下TomcatStarter,如下图:

  所以再调用TomcatStarter.onStartup方法的时候就相当于调用我们的lambda,接下来看一下lambda,如下图:

  而我们再自动配置类定义的DispatcherServletRegistrationBean就是实现了org.springframework.boot.web.servlet.ServletContextInitializer,所以此处可以拿到。

我们进一步按一下getServletContextInitializerBeans()方法,如下图:

  至此我们会调用关键类的DispatcherServletRegistrationBean.onStartup方法,来将封装在里面的DispatcherServlet跟context组件绑定父子关系,如下图:

  接着继续看一下register方法:如下图:

  接着继续看一下addRegistration方法:如下图:

  至此,Servlet、Filter、Listener组件就绑定到Tomcat中的context组件上,context组件start方法的后续就会调用三大组件的init方法:

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

标签:容器,Tomcat,Spring,Boot,Listener,源码,组件,Servlet
From: https://blog.csdn.net/qq_26733517/article/details/144350937

相关文章

  • 【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
     摘  要 社保是保障公民基本生活的重要制度。随着社保参保人数的增加和社保政策的不断调整,传统的手工操作已不能满足社保管理的需要。因此,设计和实现一个高效、安全、可靠的社保信息管理和分析系统对于有效管理和优化社保工作具有重要现实意义。市社保局社保信息管理与分......
  • springboot育婴经验分享平台-计算机毕业设计源码06078
     摘要随着现代社会对育儿知识的需求不断增长,家长们渴望找到一个可靠、便捷的平台来分享和获取育婴经验。为此,我们设计并实现了一个基于SpringBoot的育婴经验分享平台。该平台旨在为家长们提供一个互动交流的空间,让他们能够分享自己的育婴心得、求助育儿问题,并从中获得有价值......