深入springboot怎么启动tomcat

article/2025/10/28 21:19:57

深入springboot怎么启动tomcat

  • @EnableAutoConfiguration做了哪些事
    • 小总结
  • Tomcat何时启动的呢?
    • 小总结

在这里插入图片描述

这是中高级工程师面试中常问的问题。
知道现在有多卷了吧!
我记得我刚找工作那会儿,我只要8000的工资,面试官都要问这个问题。我真TM的醉了!

关于SpringBoot自动配置流程请看:深入Springboot启动流程+自动配置原理.

如果你对基本的启动原理有大致的了解,那么可以继续阅读此篇文章。否则请先阅读深入Springboot启动流程+自动配置原理.。

@EnableAutoConfiguration做了哪些事

我们知道,因为@EnableAutoConfiguration注解的存在,SpringBoot项目启动的时候,会去找到依赖包中META-INF/spring.factories文件,将文件中的自动配置类找出来,加载进内存!

那么和Tomcat相关的配置类,也存在于spring.factories之中:

在这里插入图片描述
我们发现这里配置了一个类: ServletWebServerFactoryAutoConfiguration。
这个类是干嘛用的呢?
点进去一看!
不看不知道,一看吓一尿:
在这里插入图片描述
根据上图的标识我们分三步来解释:

  1. @ConditionalOnWebApplication( type = Type.SERVLET):条件判断,如果当前的项目的类型为Servlet我才继续运行当前的ServletWebServerFactoryAutoConfiguration配置类,这里判断通过。

  2. @EnableConfigurationProperties({ServerProperties.class}),这个注解我在深入Springboot启动流程+自动配置原理.中有解释。那么呢,这里呢,就是去绑定我们application.properties中关于server的参数!
    例如:
    在这里插入图片描述
    指定我们服务的端口、地址等。在SpringBoot启动的时候就会被从application.properties中读取到当前的ServletWebServerFactoryAutoConfiguration配置类中,进行web服务的初始化!

  3. @Import(EmbeddedTomcat.class、 EmbeddedJetty.class): 这是什么? Tomcat?Jetty?并且通过@Import注解注入容器了!聪明的朋友猜到了,Tomcat/Jetty服务就是在这里进行初始化的。

好!由于我们这里研究的是TomCat,我们点进EmbeddedTomcat看看!
在这里插入图片描述
可以看到EmbeddedTomcat是一个由@Configuration修饰的静态内部配置类,向容器中注入了一个名叫TomcatServletWebServerFactory的对象(重点,后面会用到这个对象)。

这个时候有同学就有疑问了,在ServletWebServerFactoryAutoConfiguration类中通过@Import导入了三个对象:

  1. EmbeddedTomcat
  2. EmbeddedJetty
  3. EmbeddedUndertow

那这里为什么只加载了EmbeddedTomcat呢? 因为我们的@ConditionalOnClass条件注解,我们的依赖中没有Jetty和Undertow相关的类,因此EmbeddedJetty和EmbeddedUndertow不会加载。只会加载EmbeddedTomcat!

所以现在呢,重点来到了TomcatServletWebServerFactory这个对象上,我们进去看看。

在这里插入图片描述
我们发现通过new TomcatServletWebServerFactory(); 创建了一个TomcatServletWebServerFactory对象,然后构造方法设置了一系列参数。这里我们直接跳过,去看这个类中最重要的一个方法:getWebServer()
在这里插入图片描述
这个方法我们后面会做解释,划重点!!!!!

小总结

那么@EnableAutoConfiguration对于Tomcat的工作现在就做完了,做了什么事情呢?

向Spring容器中注入了一个初始化后,名叫TomcatServletWebServerFactory的对象。该对象继承自ServletWebServerFactory接口(记住)。我们现在可以认为TomCat服务准备好了,等待启动。那什么时候启动的呢?


Tomcat何时启动的呢?

这个时候就要回到我们的启动类上了:
在这里插入图片描述
这个SpringApplication.run()方法我们之前一直没有系统介绍过,这里我简单介绍一下。
首先我们点进run方法
发现首先创建了一个SpringApplication对象。
然后继续调用到了一个同名的run方法头上。
好!
重点就是这个run方法了,它做了什么事情呢?
在这里插入图片描述

我这里借鉴一下百度百科上面的解释:

public ConfigurableApplicationContext run(String... args) {//记录程序运行时间StopWatch stopWatch = new StopWatch();stopWatch.start();// ConfigurableApplicationContext Spring 的上下文ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//【1、获取并启动监听器】SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//【2、构造应用上下文环境】ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//处理需要忽略的BeanconfigureIgnoreBeanInfo(environment);//打印bannerBanner printedBanner = printBanner(environment);///【3、初始化应用上下文】context = createApplicationContext();//实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//【4、刷新应用上下文前的准备阶段】prepareContext(context, environment, listeners, applicationArguments, printedBanner);//【5、刷新应用上下文】refreshContext(context);//【6、刷新应用上下文后的扩展接口】afterRefresh(context, applicationArguments);//时间记录停止stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//发布容器启动完成事件listeners.started(context);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}
  1. 获取并启动监听器 通过加载META-INF/spring.factories 完成了 SpringApplicationRunListener实例化工作(告诉相关人员,SpringBoot要启动了,你们把自己该初始化的初始化了)
  2. 构造容器环境,简而言之就是加载系统变量,环境变量,配置文件
  3. 创建容器
  4. 实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
  5. 准备容器
  6. 刷新容器 :refreshContext(context)
  7. 刷新容器后的扩展接口

由于我们这里专门讨论TomCat的启动,所以我们其他的就不多去研究,直接找到最重要的地方:
第6步:刷新容器 ,这一步是整个SpringBoot非常重要的一步,IOC等等核心都是通过这一步来实现的。

我们进入refreshContext()方法看看:
在这里插入图片描述
好,继续点:
在这里插入图片描述

继续:
在这里插入图片描述
发现是一个接口,我们看有那些实现类:

在这里插入图片描述
哇,有那么多实现类,到底调用的是哪个呢?
java多态的知识来了
这个时候我们去看看,这个方法是谁调用的?
在这里插入图片描述
是一个叫ConfigurableApplicationContext的类调用的,那么继续去寻找,我们就会发现:
在这里插入图片描述
我们要找的实现类是这个!

点进去!

在这里插入图片描述

代码很长,我们直接去到onRefresh() 方法。
点进去:

在这里插入图片描述
妈的,继续找实现类:
在这里插入图片描述
找到和web相关的实现类进去一看:
在这里插入图片描述
来了来了
就是这个方法:
在这里插入图片描述

  1. 获取到容器中已经存在的ServletWebServerFactory对象(是不是有点熟悉?回到第一节结尾处去看看!),然后调用了什么方法?

调用了什么方法????

是不是getWebServer()!!

我们看看ServletWebServerFactory的子类(由于我这里的按理项目有两个Spring版本,不管它,正常情况下面的实现类,一种只有一个):在这里插入图片描述
其中是不是有TomcatServletWebServerFactory
而这个TomcatServletWebServerFactory是不是在@EnableAutoConfiguration环节创建好的???

好!!! 现在程序拿到了我们的TomcatServletWebServerFactory,并调用了其中的getWebServer()方法!!!!

好了,最终的决战来了。

getWebServer()方法到底做了什么??

我们到目前为止还没看到TomCat启动的任何蛛丝马迹,getWebServer()方法是我们最后的救命稻草了。

好!开始:

在这里插入图片描述

  1. 创建了一个Tomcat对象,然后一系列赋值。
  2. 调用了一个叫getTomcatWebServer()的方法。最终返回一个WebServer对象

继续:
在这里插入图片描述
new了一个TomcatWebServer对象(WebServer的子类),我们去看看它的构造方法:
在这里插入图片描述
一顿非空判断加赋值,最后调用到了initialize()方法。 看到这个名字就知道,这是什么?

初始化

在这里插入图片描述
Tomcat启动了。

小总结

在 SpringApplication.run()中,刷新容器的时候,程序会去找到在@EnableAutoConfiguration阶段创建好的ServletWebServerFactory,它的实现类可能是TomCat可能是Jetty,根据我们项目所引入的依赖自动实例化。

最后由ServletWebServerFactory调用getWebServer()方法启动web容器。
在这里插入图片描述



🍅你的点赞收藏是我分享的动力,谢谢。🍅


http://chatgpt.dhexx.cn/article/S1OpALhN.shtml

相关文章

Windows如何设置Tomcat开机启动?

前置步骤&#xff1a; 在tomcat中的bin目录下&#xff0c;双击startup.bat运行tomcat&#xff0c; 在浏览器正常打开Tomcat情况下&#xff0c;说明tomcat安装正常&#xff0c;双击shutdown.bat停掉tomcat 第一步&#xff1a; 1、设置环境变量 2、在 用户变量 新建 CATALINA_H…

Linux服务器启动tomcat的三种方式

直接进入主题&#xff0c;首先cd进入tomcat的bin文件夹下&#xff0c;然后可以尝试以下三种启动方式&#xff1a; 第一种&#xff08;当前会话启动&#xff09;&#xff1a; ./startup.sh 效果: 然后tomcat就在后台启动了&#xff0c;我们还可以在当前会话中继续输入其它指令…

Tomcat-启动流程

文章目录 叨叨程序入口加载load流程简述Bootstrap.load()Catalina.load(params)init()模板方法init流程总结 start()模板方法流程简述start()模板方法Host.start()特别说明 叨叨 讲真&#xff0c;最开始源码调试几遍下来还是很懵了&#xff0c;尤其是组件初始化过程中不断去调用…

java教程(三)初识J2ee十三个规范

&#xfeff;&#xfeff; 我目前是个java未入门的新手&#xff0c;这边看到高手的一些文章&#xff0c;转载过来。---haogting J2EE是一套全然不同于传统应用开发的技术架构&#xff0c;主要可简化且规范应用系统的开发与部署&#xff0c;进而提高可移植性、安全与复用价值。 …

J2EE【开发环境搭建】

EasyUI【DataGrid数据查询】_云彩123的博客-CSDN博客_easyui 获取datagrid数据如需温习上一节内容&#xff0c;请点击下方链接进行跳转&#xff1a;EasyUI(Tree后端工作)_云彩123的博客-CSDN博客用户信息表&#xff08;T_User&#xff09;列名数据类型长度允许空默认值说明idva…

J2EE(环境搭建)

目录 一、jdk安装&环境配置 A、拿到exe文件 B、默认安装位置 C、配置环境变量 D、注意事项 二、Eclipse安装&设置默认编码集 A、解压 B、选择工作区间 C、设置默认编码集 Ca、设置jsp默认编码 Cb、设置workspace编码方式 三、配置Tomcat及JDK A、配置Tomcat …

java quartz 教程_Quartz 教程

一、关于 Quartz Quartz logo Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。 Quartz 可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。 Quartz 允许程序开发人员根据时间的间隔来调度作业。 Quartz 实现了作…

J2EE入门:环境搭建

前言&#xff1a; JDK的安装以及JDK的环境配置 tomcat的安装 Eclipce的环境配置 MySQL的安装 JDK安装以及环境配置 直接点击JDK安装包安装 JDK默认安装位置&#xff1a;C:\Program Files\Java 然后双击jdk144文件夹 进来之后选中地址栏复制地址 然后退出至桌面,右键桌面…

J2EE之旅(入门)

从这次开始我们就要开始学习j2ee&#xff0c;我们先来介绍一下我们将要使用到的 1.测试工具&#xff1a;ApiPost_Setup_5.4.2_x64.exe 2.开发工具:vs 3.数据库&#xff1a;考虑了多方面&#xff0c;数据库我们就选用mysql 4.数据库可视化工具&#xff1a; 由于这些软件安装大部…

J2EE入门教程

2005-12-11 20:20:21 J2EE入门教程本教程讲述Sun J2EE 1.3 SDK的安装、配置和创建并部署第一个简单的EJB。我们的目标平台是Windows XP SP2&#xff0c;JDK 1.4.2和J2EE SDK 1.3.1的Windows版本。我们在下面的实践中主要使用命令行模式&#xff0c;便于深入J2EE的内部机制。首先…

如何拥有个人的Github技术博客

题图&#xff1a;87testing.com 前不久用wordpress搭建了一个博客&#xff0c;用起来感觉不是太好用&#xff0c;并且数据库经常会发生异常挂掉&#xff0c;没找到解决方案。 看到有不少人使用的hexogithub方式搭建属于自己的博客&#xff0c; 于是&#xff0c;我也做了一些尝试…

github博客+hexo

这里基于ubuntu18&#xff0c;win10其实一样的&#xff0c;把sudo去掉就行了 安装 安装git 配置github的ssh 安装Node.js 版本需不低于 10.13&#xff0c;建议使用 Node.js 12.0 及以上版本 建议换个源 npm install express --registryhttps://registry.npm.taobao.org在gi…

【hexo+gitee/github】博客搭建

文章目录 参考资料1. 使用gitee&#xff08;github&#xff09;与hexo好处2. 安装2.1 安装Nodejs2.2 安装git2.3 安装Hexo 3. 建站4. 启动5. 配置5.1 主题配置 6. 部署到gitee pages6.1 创建一个gitee仓库6.2 配置路径6.3 开启GiteePages服务6.4 github pages部署6.4. 博客源代…

hexo+github部署个人博客

文章目录 hexogithub部署个人博客前期准备hexo搭建个人博客新建GitHub仓库将个人博客部署到Git pages写文章和发布文章Hexo优化修改博客目录下的_config.yml配置 matery主题美化 hexogithub部署个人博客 前期准备 安装git git的下载地址安装node.js node.js注册github账号&am…

利用github进行自定义博客地址

写在前面&#xff1a; 大家好&#xff0c;我是 花狗Fdog &#xff0c;来自内蒙古的一个小城市&#xff0c;目前在泰州读书。 很感谢能有这样一个平台让我能够在这里分享所学所感。 我喜欢编程&#xff0c;喜欢代码&#xff0c;喜欢去做一个程序员。 努力学习&#xff0c;争取多…

如何搭建github.io博客

零、宣传我的Github.io博客 https://ruixiangjiang.github.io/ 如果我的电脑没开就不能访问。。。正在调试中。。。 一、注册一个账号 进入www.github.com &#xff0c;然后注册。首页右上角头像那里有一个“”号&#xff0c;点击后选择“New repositor”。创建完之后点击“…

使用Github.io打造个人博客网站

Github.io上可以方便地打造自己的博客网站&#xff0c;相对于CSDN等社区网站来说既没有广告又能凸显个人调性。 建站步骤 建站步骤非常简单 在个人github上建一个repository&#xff0c;名字必须是username.github.io 推送一个静态html上去 # clone the prj git clone htt…

搭建hexo+Github博客

摘要 本文主要向大家介绍了如何搭建hexo-Github博客的详细过程&#xff0c;有需要的朋友们可以尝试阅读&#xff0c;希望对大家有帮助。 简要吐槽 搭博客其实没那么麻烦&#xff0c;但是在网上各类教程的“指导下”&#xff0c;我不知道放弃了多少次又重新试了多少次&#xff…

GitHub: 个人博客搭建

GitHub: 个人博客搭建 食材&#xff1a;jekyll 工具&#xff1a;GitHub&#xff0c;visual studio code&#xff0c;chrome。 第一步&#xff1a;安装Jekyll&#xff0c;具体参考官方链接 https://www.jekyll.com.cn/docs/step-by-step/01-setup/ 操作指南 安装一个完整的…

hexo+github搭建博客(超级详细版,精细入微)

转载此文章前&#xff0c;请先联系作者&#xff0c;经作者同意后再转载&#xff0c;并请注明原文链接和作者&#xff0c;整理这些不容易&#xff0c;最终版权归作者所有&#xff0c;谢谢合作&#xff01;移步我的个人博客&#xff1a;https://yafine-blog.cn&#xff0c;阅读体…