spring boot是如何加载Tomcat的

news2025/2/24 11:40:53

目录

  • spring boot是如何加载Tomcat的
    • 1. 方法入口
    • 2. SpringContext上下文
    • 3. 创建web容器
    • 4. 启动web容器
    • 结语

spring boot是如何加载Tomcat的

大家都用过spring boot,都知道他启动的时候内置一个Tomcat,但是他是怎么来的,你们知道吗

这篇博客将带你们走进spring boot的源码,看看spring boot底层是如何加载tomcat的,走起发车!

1. 方法入口

入口SpringApplication.run()这个方法大家都很熟悉我就不细讲了,我们从这进去一直找到public ConfigurableApplicationContext run(String... args),然后找到refreshContext这个方法

public ConfigurableApplicationContext run(String... args) {
      //此处省略
 	  //入口方法
     this.refreshContext(context);
      //此处省略
}

继续往refresh这个方法找,一直跟着refresh找,直到找到ConfigurableApplicationContext的抽象类

private void refreshContext(ConfigurableApplicationContext context) {
    this.refresh((ApplicationContext)context);
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        } catch (AccessControlException var3) {
        }
    }

}

2. SpringContext上下文

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
  //此处省略
   //web容器上下文入口
   void refresh() throws BeansException, IllegalStateException;
   //此处省略

}

我们找到他的实现类,我们看到有三个对不对,这时候我们选择AbstractApplicationContext,不要选ServletWebServerApplicationContext,因为ServletWebServerApplicationContextAbstractApplicationContext的子类,我们先看他的抽象方法

在这里插入图片描述

进入到AbstractApplicationContext中,我们重点看onRefresh方法

这是Spring 源码中的核心代码,这是一个模板方法,里面有个很多钩子函数,这里我就不省略代码了,因为这段代码很重要,在这里我们可以看到spring 的生命周期。

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        this.prepareBeanFactory(beanFactory);

        try {
            this.postProcessBeanFactory(beanFactory);
            this.invokeBeanFactoryPostProcessors(beanFactory);
            this.registerBeanPostProcessors(beanFactory);
            this.initMessageSource();
            this.initApplicationEventMulticaster();
            //加载bean
            this.onRefresh();
            this.registerListeners();
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }

            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }

    }
}

点进去他是一个空实现

protected void onRefresh() throws BeansException {
}

我们 找到他的实现类ServletWebServerApplicationContext,这是加载web容器的上下文,我们可以明显看到createWebServer就是一个创建web容器的方法

protected void onRefresh() {
    super.onRefresh();

    try {
        //创建web容器
        this.createWebServer();
    } catch (Throwable var2) {
        throw new ApplicationContextException("Unable to start web server", var2);
    }
}

3. 创建web容器

我们进去源码继续看,有个getWebServerFactory方法,这是获取webserver工厂类的方法,相信我们离真相不远了

private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = this.getServletContext();
    if (webServer == null && servletContext == null) {
        //获取webServerr工厂
        ServletWebServerFactory factory = this.getWebServerFactory();
        //通过工厂生成webServer
		this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
    }
    this.initPropertySources();
}

我们继续看可以看到其实我们是获取ServletWebServerFactory的bean,那ServletWebServerFactory具体有什么实现呢

protected ServletWebServerFactory getWebServerFactory() {
    String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
    //此处省略
}

看到这是不是很清晰啦,我们直接找到TomcatServletWebServerFactory,看他的getWebServer实现
在这里插入图片描述

很清晰的看到,这就是tomcat的配置,host,connector之类的,相信以前我们学tomcat的时候都见过

public WebServer getWebServer(ServletContextInitializer... initializers) {
    if (this.disableMBeanRegistry) {
        Registry.disableRegistry();
    }

    Tomcat tomcat = new Tomcat();
    File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    Connector connector = new Connector(this.protocol);
    connector.setThrowOnFailure(true);
    tomcat.getService().addConnector(connector);
    this.customizeConnector(connector);
    tomcat.setConnector(connector);
    tomcat.getHost().setAutoDeploy(false);
    this.configureEngine(tomcat.getEngine());
    Iterator var5 = this.additionalTomcatConnectors.iterator();

    while(var5.hasNext()) {
        Connector additionalConnector = (Connector)var5.next();
        tomcat.getService().addConnector(additionalConnector);
    }

    this.prepareContext(tomcat.getHost(), initializers);
    //启动web容器
    return this.getTomcatWebServer(tomcat);
}

4. 启动web容器

tomcat是在上文中的getTomcatWebServer中启动的,我们再深入进去

protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
    return new TomcatWebServer(tomcat, this.getPort() >= 0, this.getShutdown());
}

这是一个TomcatWebServer的构造方法,我们再点进去

public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
    //此处省略
    //初始化tomcat
    this.initialize();
}

进入initialize方法,不用说大家都知道tomcat.start就是启动tomcat啦

private void initialize() throws WebServerException {
    logger.info("Tomcat initialized with port(s): " + this.getPortsDescription(false));
    synchronized(this.monitor) {
        try {
            this.addInstanceIdToEngineName();
            Context context = this.findContext();
            context.addLifecycleListener((event) -> {
                if (context.equals(event.getSource()) && "start".equals(event.getType())) {
                    this.removeServiceConnectors();
                }

            });
            // 启动tomcat
            this.tomcat.start();
            this.rethrowDeferredStartupExceptions();

            try {
                ContextBindings.bindClassLoader(context, context.getNamingToken(), this.getClass().getClassLoader());
            } catch (NamingException var5) {
            }

            this.startDaemonAwaitThread();
        } catch (Exception var6) {
            this.stopSilently();
            this.destroySilently();
            throw new WebServerException("Unable to start embedded Tomcat", var6);
        }

    }
}

结语

这篇文章下来,是不是感觉以前不理解的东西一下子就清晰了呢,这篇文章希望能帮助大家能更简单的去了解源码,学习总是快乐的嘿嘿

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

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

相关文章

cudann官网上不见了,找不到了安装CUDA和CUDANN时,发现CUDANN不见了,官网甚至找不到一丝它的信息,公告也没有

我在习惯性的安装CUDA和CUDANN时,发现CUDANN不见了,官网甚至找不到一丝它的信息,公告也没有,看看吐槽 说实话最开始的CUDANN确实比较恼火,要下载下来拷贝过去 现在只需要直接安装cuda,就可以安装成功了 C…

XJAR 混淆加密

一&#xff1a;手动加密 pom依赖 <repositories><repository><id>jitpack.io</id><url>https://jitpack.io</url></repository> </repositories> <dependencies><dependency><groupId>com.github.core-l…

2023年CSP-J 普及组第一轮题目和答案详解

家人们首战报捷&#xff01;&#xff01;&#xff01;&#xff01; 才教了一个月的学生&#xff0c;赛前一周才报名CSP-J都没提前安排初赛内容临时周内加了两节课&#xff0c; 总共初赛也就上了3次课准备了不到一周半&#xff0c;压线进了复赛&#xff0c; 不得不说学生基础还不…

Python是人工智能的最佳选择吗?看看它的优势和局限

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是当今科技领域最热门的话题之一&#xff0c;它涉及到计算机科学、数学、统计学、心理学等多个学科的交叉和融合。人工智能的目标是让机器能够模拟和超越人类的智能&#xff0c;实现自主学习、推理、决策…

Kotlin协程CoroutineScope异步async取消cancel等待await的任务

Kotlin协程CoroutineScope异步async取消cancel等待await的任务 import kotlinx.coroutines.*fun main(args: Array<String>) {runBlocking {val mScope CoroutineScope(Dispatchers.IO).async {println("->")delay(999999)println("<-")"…

施耐德电气携中国信通院和中国联通共同发布白皮书,共探5G+PLC深度融合应用

2023年9月20日——全球能源管理和自动化领域的数字化转型专家施耐德电气在第23届中国国际工业博览会首日的9月19日&#xff0c;与中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;及中国联合网络通信集团有限公司&#xff08;以下简称“中国联通”&#xff0…

配置 iSCSI 服务并实现客户端自动挂载块设备

文章目录 前言1. iSCSI 简介2. iSCSI Server 端配置2.1. 添加磁盘2.2. 安装 targetcli 软件包2.3. 创建块设备2.4. 创建 Target2.5. 创建 LUN2.6. 创建 ACL2.7. 配置门户创建监听2.8. 查看全部配置信息并保存退出2.9. 启用 Target 服务 3. iSCSI Client 端配置3.1. 安装 iscsi-…

前端框架vBean admin

文章目录 引言I 数据库表设计1.1 用户表1.2 角色表1.3 菜单表II 接口引言 文档:https://doc.vvbin.cn/guide/introduction.html http://doc.vvbin.cn 仓库:https://github.com/vbenjs/vue-vben-admin git clone https://github.com/vbenjs/vue-vben-admin-doc 在线体验demo:…

台积电没有想到,当初拒绝的中国芯片企业,如今反过来抢夺市场了,后悔莫及...

台积电二季度的营收已经出现下滑&#xff0c;本来它希望四季度在以往苹果销售旺季的支持下再度推高收入&#xff0c;然而如今中国手机企业自研的国产5G芯片正在反过来抢占市场&#xff0c;台积电四季度的收入恐怕也将下降。 苹果的销售旺季为每年的四季度&#xff0c;不过此时恰…

通过已有虚拟机快照创建虚拟机

我们在搭建redis、k8s等集群的时候&#xff0c;需要创建多台虚拟机&#xff0c;而且这几台虚拟机的配置基本上是一样的&#xff0c;这种情况下我们可以先创建一台虚拟机&#xff0c;安装需要的应用后导出快照&#xff0c;然后通过快照生成其他的虚拟机 1、生成快照 2、通过快照…

用小程序,轻松识别纸质表格并转换成Excel表格,解放双手

来百度APP 职场小伙伴们&#xff0c;有没有遇到过将纸质表格转化为Excel表格的任务&#xff1f;如果你没有经验&#xff0c;手工处理不仅效率低&#xff0c;而且容易出错。这真是一个费时费力的任务呀&#xff01;但别担心&#xff0c;现在我们有更好的解决方案——百度小程序…

neo4j下载安装配置步骤

目录 一、介绍 简介 Neo4j和JDK版本对应 二、下载 官网下载 直接获取 三、解压缩安装 四、配置环境变量 五、启动测试 一、介绍 简介 Neo4j是一款高性能的图数据库&#xff0c;专门用于存储和处理图形数据。它采用节点、关系和属性的图形结构&#xff0c;非常适用于…

大模型训练之加速篇 -attention优化【MQA-> flashAttention】

MQA (multi query attention) Fast Transformer Decoding: One Write-Head is All You Need MQA 是 19 年提出的一种新的 Attention 机制&#xff0c;其能够在保证模型效果的同时加快 decoder 生成 token 的速度。 那到底能提升多少的速度呢&#xff0c;我们来看论文中给出的结…

慢SQL原因分析之索引失效 | 京东物流技术团队

现象 最近收到一个慢sql工单,慢sql大概是这样&#xff1a;“select xxx from tabel where type 1”。 咦&#xff0c;type字段明明有索引啊&#xff0c;为啥是慢sql呢&#xff1f; 原因 通过执行explain&#xff0c;发现实际上数据库执行了全表扫描&#xff0c;从而被系统…

excel的vlookup函数用法

vlookup函数功能&#xff1a;在表格的首列查找指定的数值&#xff0c;并返回表格当前行中指定列处的数值。 结构&#xff1a;VLOOKUP(查找值,查找区域,列序数,匹配条件) 解释&#xff1a;VLOOKUP(找谁,在哪里找,第几列,0或1) 说明&#xff1a; 1、第一参数&#xff1a;查找…

【Linux is not Unix】Linux前言

目录 二战军工的产物——第一台现代电子数字计算机ENIAC&#xff08;埃尼阿克&#xff09; Unix Linux Linux企业应用现状 如今计算机已经应用在我们生活的各个层面&#xff0c;像我们日常使用的笔记本是计算机的一类&#xff0c;可以解决我们生活中遇到的很多问题&#xff…

【数据分享】2023年全国乡镇(街道)点位数据(免费获取\shp格式\excel格式)

乡镇&#xff08;街道&#xff09;点位数据是我们各项研究中经常使用到的数据&#xff0c;在之前的文章中我们分享过2022年度的乡镇&#xff08;街道&#xff09;点位数据&#xff08;可查看之前推送的文章获悉详情&#xff09;。本次我们带来的是2023年度的全国范围的乡镇&…

Labelme分割标注软件

Labelme分割标注软件 1、环境配置与安装1.1 创建conda虚拟环境(建议)1.2 安装Labelme 2、简单使用2.1 创建label标签文件2.2 启动labelme2.3 打开文件/文件夹2.4 设置保存结果路径2.5 标注目标2.6 保存json文件格式 3 格式转换3.1 转换语义分割标签3.2 转换实例分割标签 相关重…

CUDA小白 - NPP(11) 图像处理 Comparison Operations

cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xf…

显示器有白点闪烁、间歇黑屏解决办法

问题描述 以上三张图片是不到一秒内通过手机视频拍摄显示器画面&#xff0c;可以看到第一张图大桥下和第二张图片右下角岛屿初均有红点闪烁。当触发黑屏时&#xff0c;显示器整体白点闪烁。并且时常黑屏&#xff0c;几秒后恢复。 解决办法 检查HDMI连接线是否脱落&#xff0c…