【SpringBoot】SpringBoot内置Servlet容器源码分析-Tomcat

自动装配加载 ServletWebServerFactoryAutoConfiguration

在这里插入图片描述
在自动装配的时候,会加载spring.factories,并且添加到IOC容器中。这里包含web自动配置类ServletWebServerFactoryAutoConfiguration ,其中本类中注入三个bean,分别是EmbeddedTomcat\EmbeddedJetty\EmbeddedUndertow, 以及可以添加自定义BD的BeanPostProcessorsRegistrar

@Configuration(proxyBeanMethods = false) // 配置类
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 自动装配的顺序
@ConditionalOnClass(ServletRequest.class) //  引入Servlet的依赖才生效
@ConditionalOnWebApplication(type = Type.SERVLET) // 当Web容器是Servlet才生效
@EnableConfigurationProperties(ServerProperties.class) // 关联对应的属性配置类
// 通过 @Import注解引入一些Web容器
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,// 引入一些对应的容器的类对象ServletWebServerFactoryConfiguration.EmbeddedJetty.class,ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {/*** 这里注入了一个ServletWebServer的定制工厂* @param serverProperties* @return*/@Beanpublic ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {return new ServletWebServerFactoryCustomizer(serverProperties);}@Bean@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {return new TomcatServletWebServerFactoryCustomizer(serverProperties);}/*** Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via* {@link ImportBeanDefinitionRegistrar} for early registration.*/public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {private ConfigurableListableBeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {if (beanFactory instanceof ConfigurableListableBeanFactory) {this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;}}@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {if (this.beanFactory == null) {return;}// 向容器中注册了一个后置处理器registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",WebServerFactoryCustomizerBeanPostProcessor.class);registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",ErrorPageRegistrarBeanPostProcessor.class);}private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);beanDefinition.setSynthetic(true);registry.registerBeanDefinition(name, beanDefinition);}}}}

初始化和启动 tomcat

在ioc容器刷新时候,进行自定义拓展,实现tomcat的创建。

	protected void onRefresh() {super.onRefresh();try {createWebServer();}catch (Throwable ex) {throw new ApplicationContextException("Unable to start reactive web server", ex);}}// tomcat执行private void createWebServer() {WebServer webServer = this.webServer;ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) {ServletWebServerFactory factory = getWebServerFactory();// 获取WebServer的工厂对象this.webServer = factory.getWebServer(getSelfInitializer()); // 获取具体的WebServer}else if (servletContext != null) {try {getSelfInitializer().onStartup(servletContext);}catch (ServletException ex) {throw new ApplicationContextException("Cannot initialize servlet context", ex);}}initPropertySources();}// 获取tomcat工厂  调用getBean会进行初始化、实例化操作protected ServletWebServerFactory getWebServerFactory() {// Use bean names so that we don't consider the hierarchyString[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);if (beanNames.length == 0) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "+ "ServletWebServerFactory bean.");}if (beanNames.length > 1) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));}return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);}

创建tomcat对象

	public WebServer getWebServer(ServletContextInitializer... initializers) {if (this.disableMBeanRegistry) {Registry.disableRegistry();}Tomcat tomcat = new Tomcat();// 创建Tomcat容器,并且配置连接器,引擎等属性File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());Connector connector = new Connector(this.protocol);// 创建连接器connector.setThrowOnFailure(true);// 给service添加connectortomcat.getService().addConnector(connector);// 定制自己的连接器customizeConnector(connector);// 设置到tomcat中tomcat.setConnector(connector);// 自动部署 falsetomcat.getHost().setAutoDeploy(false);configureEngine(tomcat.getEngine()); // 配置Enginefor (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);// Service关联Connector}prepareContext(tomcat.getHost(), initializers);return getTomcatWebServer(tomcat); // 获取TomcatWebServer}public TomcatWebServer(Tomcat tomcat, boolean autoStart) {Assert.notNull(tomcat, "Tomcat Server must not be null");this.tomcat = tomcat;this.autoStart = autoStart;initialize(); // 非常重要的初始化方法 ⭐️}// 启动Tomcat通过发布事件触发一些Listener的初始化  也只是完成tomcat的初始化工作this.tomcat.start();// 启动tomcatprotected void finishRefresh() {super.finishRefresh();WebServer webServer = startWebServer();if (webServer != null) {publishEvent(new ServletWebServerInitializedEvent(webServer, this));}}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/42323.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Threejs将场景生成全景图导出

实现思路&#xff1a; 创建全景相机CubeCamera&#xff08;六个方位的透视相机&#xff09;并渲染场景 读取六个面的纹理数据 填充进canvas中 即可按照常规的canvas导出图片了 demo https://gitee.com/honbingitee/three-template-next.js/tree/HDR 核心代码 const cubeRender…

分享大厂对于缓存操作的封装

hello&#xff0c;伙伴们好久不见&#xff0c;我是shigen。发现有两周没有更新我的文章了。也是因为最近比较忙&#xff0c;基本是993了。 缓存大家再熟悉不过了&#xff0c;几乎是现在任何系统的标配&#xff0c;并引申出来很多的问题&#xff1a;缓存穿透、缓存击穿、缓存雪崩…

C语言调试技巧

叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.bug 是什么2.debug 是什么3.两种模式的区别4.IDE 调试介绍4.1.模…

嵌入式c语言5——位运算符

<<与>>是c语言中两个移位运算符&#xff0c;分别有乘以2与除以2的意义 位运算符还包括&#xff0c;与&&#xff0c;或|&#xff0c;均进行按位操作 同时&#xff0c;还可以进行取反以及异或操作

synchronized和ReentrantLock

ReentrantLock ReentrantLock fairLock new ReentrantLock(true);// 这里是演示创建公平锁&#xff0c;一般情况不需要。 fairLock.lock(); try {// do something } finally {fairLock.unlock(); }

商家店铺电商小程序模板源码

橙色通用的商家入驻&#xff0c;商户商家&#xff0c;商家店铺&#xff0c;购物商城&#xff0c;商家购物平台app小程序网页模板。包含&#xff1a;商家主页、优先商家、商品详情、购物车、结算订单、个人中心、优惠券、会员卡、地址管理等功能页面。 商家店铺电商小程序模板源…

基于CentOS Stream 9平台搭建RabbitMQ3.13.4以及开机自启

1. erlang与RabbitMQ对应版本参考&#xff1a;https://www.rabbitmq.com/which-erlang.html 2. 安装erlang 官网&#xff1a;https://www.erlang.org/downloads GitHub: https://github.com/rabbitmq/erlang-rpm/releases 2.1 安装依赖&#xff1a; yum -y install gcc glib…

Nginx实战:nginx性能压测(ab)

在nginx的生产实践中,不管是服务上线,还是性能优化,都会遇到需要对nginx的性能压测,本文介绍一个简单的压测工具:ab命令 ab(Apache Bench)是一个常用的HTTP压力测试工具,可以用来测试Nginx的性能和压力。ab命令可以指定并发请求数、请求数、请求类型等参数,并输出测试…

550kg级大载重长航时无人机直升机技术详解

550kg级大载重长航时无人机直升机&#xff0c;作为一种高性能的无人机系统&#xff0c;具备了多项先进的技术特点&#xff0c;以满足高海拔、高寒等复杂环境下的应用需求。这些无人机直升机通常具备高载重、长航时、强适应性、高可靠性和良好的任务拓展性。 设备由无人直升机平…

【面试八股文】java基础知识

引言 本文是java面试时的一些常见知识点总结归纳和一些拓展&#xff0c;笔者在学习这些内容时&#xff0c;特地整理记录下来&#xff0c;以供大家学习共勉。 一、数据类型 1.1 为什么要设计封装类&#xff0c;Integer和int区别是什么&#xff1f; 使用封装类的目的 对象化:…

数据结构——单链表专题

前言 本篇我们继续来介绍数据结构的知识——链表&#xff0c;这与顺序表是一个类别的知识&#xff0c;同样也非常重要&#xff0c;所以大家需要掌握好链表的内容&#xff0c;这对我们后面数据结构的学习也很重要&#xff0c;如果你对本篇的内容感兴趣&#xff0c;希望大佬可以…

四大常见的排序算法JAVA

1. 冒泡排序 相邻的元素两两比较&#xff0c;大的放右边&#xff0c;小的放左边 第一轮比较完毕之后&#xff0c;最大值就已经确定&#xff0c;第二轮可以少循环一次&#xff0c;后面以此类推 如果数组中有n个数据&#xff0c;总共我们只要执行n-1轮的代码就可以 package Bu…

【matlab】状态空间模型与传递函数模型的建立与转换

目录 SISO系统 MIMO系统 状态空间模型 状态空间模型到传递函数模型的转换 传递函数模型到状态空间模型的转换 (1) 转换函数ss() (2) 规范形转换函数canon() (3) 常微分方程(传递函数)转换为状态空间模型函数dif2ss() 状态空间模型的变换 特征值、特征向量与广义特征向量的计算…

everything高级搜索-cnblog

everything高级搜索用法 基础4选项验证 总结搜索方式 高级搜索搜指定路径文件名: 文件名 路径不含文件名: &#xff01;文件名包含单词 路径包含指定内容: 路径 content:内容 大小写 区分大小写搜索搜指定路径文件名: case:文件名 路径全字匹配 全字搜指定路径文件名: wholewo…

中霖教育:二级建造师未注册还需要继续教育吗?

关键词&#xff1a;中霖教育怎么样&#xff0c;中霖教育口碑 如果通过了二级建造师考试但是没有注册&#xff0c;还用继续教育吗? 1. 未注册的二级建造师 二级建造师在其证书获取后三年内没有进行注册时&#xff0c;在申请初始注册之前必须完成规定的本专业继续教育课程。 …

ubuntu运行qq音乐闪退

ubuntu运行qq音乐闪退 修改/usr/share/applications中的qqmusic.desktop&#xff0c;在Exec后加上 --no-sandbox,如下图所示&#xff1a; 该文件有可能是只读&#xff0c;权限不够的话用sudo vim qqmusic.desktop

java项目的一些功能(完善登录功能、注册接口参数校验、完善分页查询、完善日期格式、更新文章分类和添加文章分类的分组校验、自定义校验、文件上传 )

目录 完善登录功能 注册接口参数校验 完善分页查询 完善日期格式 更新文章分类和添加文章分类的分组校验 ​编辑 自定义校验 文件上传 完善登录功能 对前端传过来的明文密码进行md5加密处理 password DigestUtils.md5DigestAsHex(password.getBytes()); 这样既可 注…

Python数据分析案例50——基于EEMD-LSTM的石油价格预测

案例背景 很久没更新时间序列预测有关的东西了。 之前写了很多CNN-LSTM&#xff0c;GRU-attention&#xff0c;这种神经网络之内的不同模型的缝合&#xff0c;现在写一个模态分解算法和神经网络的缝合。 虽然eemd-lstm已经在学术界被做烂了&#xff0c;但是还是很多新手小白或…

驾校管理系统的全面革新与升级

智慧驾校系统是一款专为现代驾校量身定制的综合性管理平台,它深度融合了云计算、大数据、物联网及人工智能等前沿技术,旨在为驾校打造一个高效、智能、便捷的运营生态系统。该系统通过数字化、信息化的手段,彻底革新了传统驾校的管理模式,不仅极大地提升了驾校的运营效率,…

Open3D 点云CPD算法配准(粗配准)

目录 一、概述 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2配准后点云 一、概述 在Open3D中&#xff0c;CPD&#xff08;Coherent Point Drift&#xff0c;一致性点漂移&#xff09;算法是一种经典的点云配准方法&#xff0c;适用于无序点云的非…