从源码层面看spring boot tomcat启动流程_springboot项目,tomcat启动时序_talen_hx296的博客-程序员秘密

技术标签: spring boot  spring cloud  

spring boot 启动tomcat流程,网上已经很多,这里只是给自己以后看,总结,不好勿喷,谢谢.

自动配置类流程:SpringBootApplication>>EnableAutoConfiguration>>
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors>>
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)>>
#invokeBeanDefinitionRegistryPostProcessors>>

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions>>

org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)>>

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports>>

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports>>

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process>>

#getAutoConfigurationEntry>>

#getCandidateConfigurations>>

#loadFactoryNames>>

#loadSpringFactories

启动流程总归以下三点:

1.spring 的生命周期中,留给后面开发的后门,这里并不是指后置处理器BeanPostProcessor

2.spring boot 中自动加载配置类,读取 META-INF/spring.factories 里面的配置类

3.SPI机制

一、读取并初始化依赖里面, META-INF/spring.factories 配置好的接口实现类,此时也利用spi机制

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //设置webapplicationType,这里后续会用到,WebApplicationType#SERVLET
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //这里加载META-INF/spring.factories,自动加载配置
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

二、在ServletWebServerApplicationContext类中,重写了onRefresh方法,添加了 createWebServer方法,用来启动tomcat,这里重点是这段代码行

ServletWebServerFactory factory = getWebServerFactory();

这里是获得启动容器类型,比如是tomccat,jetty,undertow,这里从debug来看TomcatServletWebServerFactory,但是它从哪里来呢?从前面的代码中看到,并没有实例此类,初步猜想应该是spring 容器里实现化了,先不管,继续向下看逻辑。

三、看到TomcatServletWebServerFactory中的getWebServer方法,就已经知道tomcat是如何创建的了

@Override
	public WebServer getWebServer(ServletContextInitializer... initializers) {
		if (this.disableMBeanRegistry) {
			Registry.disableRegistry();
		}
		Tomcat tomcat = new Tomcat();
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
		tomcat.setBaseDir(baseDir.getAbsolutePath());
		Connector connector = new Connector(this.protocol);
		connector.setThrowOnFailure(true);
		tomcat.getService().addConnector(connector);
		customizeConnector(connector);
		tomcat.setConnector(connector);
		tomcat.getHost().setAutoDeploy(false);
		configureEngine(tomcat.getEngine());
		for (Connector additionalConnector : this.additionalTomcatConnectors) {
			tomcat.getService().addConnector(additionalConnector);
		}
		prepareContext(tomcat.getHost(), initializers);
		return getTomcatWebServer(tomcat);
	}

这就不需要解释了,就是设置tomcat参数,并启动,跟tomcat中间件是一套逻辑

四、回过头来,看看TomcatServletWebServerFactory是如何创建的,这里就是SPI机制作用了

这里根据经验,可以猜测应该是跟webServer有关的配置类,可以找到ServletWebServerFactoryAutoConfiguration, EmbeddedWebServerFactoryCustomizerAutoConfiguration 到底哪个呢?这里只能点进去看类的实现,终于发现是ServletWebServerFactoryAutoConfiguration中,ServletWebServerFactoryConfiguration.EmbeddedTomcat这个类

@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
	@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
	static class EmbeddedTomcat {

		@Bean
		TomcatServletWebServerFactory tomcatServletWebServerFactory(
				ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
				ObjectProvider<TomcatContextCustomizer> contextCustomizers,
				ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
			TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
			factory.getTomcatConnectorCustomizers()
					.addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
			factory.getTomcatContextCustomizers()
					.addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
			factory.getTomcatProtocolHandlerCustomizers()
					.addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
			return factory;
		}

	}

这里就是实现化然后交给spring管理.

在此就可以将整个流程串起来了。

写得比较跳,仅供自己看,梳理.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/talen_hx/article/details/119563107

智能推荐

机票预订系统(Java)_Bowen_Yang的博客-程序员秘密

下载地址(需要1积分):https://download.csdn.net/download/qq_39627843/10767124(我已经做出了本系统的改进版2.0,地址如下:https://blog.csdn.net/qq_39627843/article/details/85608395)系统主要包含三个功能:机票查询,机票预订,机票退订。现在看了一下,上面的链接下载要20...

使用podman容器配置gitlab_podman gitlab_witton的博客-程序员秘密

文章目录一、下载gitlab以及gitlab-runner镜像二、运行容器与配置gitlab1、运行gitlab容器2、修改配置三、运行与注册gitlab-runner1、运行gitlab-runner2、进入容器Bash3、注册gitlab-runner一、下载gitlab以及gitlab-runner镜像sudo podman pull docker.io/gitlab/gitlab-eesudo podman pull docker.io/gitlab/gitlab-runner笔者下载的版

第十四届华中科技大学程序设计竞赛 部分有趣题的题解(A, C, I, L)_Anxdada的博客-程序员秘密

传送门A: 题意: 就是定义树上的一个三元组(a, b, c) 成立的条件是|dis(a, c) - dis(b, c)| % 2 == n % 2; 给定一棵树, 问树上这样的三元组有多少个.思路: 分析可知, 我们肯定是把枚举c, 然后判断每一个c有多少个a, b, 可以填, 然后我们发现填这个是和n的奇偶性有关, n为奇, 那么一定时奇-偶(或者相反), 那么我们要知道的就是对于树上每...

黑马程序员_7K面试题--银行业务调度系统_weixin_30580943的博客-程序员秘密

银行业务调度系统模拟实现银行业务调度系统逻辑,具体需求如下:银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)异步随机生成各种类型的客户,生成各类型用户的概率比例为: VIP客户 :普通客户 :快速...

cc2530裸机编程系列笔记3--定时器Timer1自由模式程序_霜月孤鸟的博客-程序员秘密

定时器1是一个16 位定时器,具有定时器/计数器/脉宽调制功能。它有3 个单独可编程 输入捕获/输出比较信道,每一个信道都可以用来当做PWM 输出或用来捕获输入信号的边沿时间(关于什么是输入捕获/输出比较,以及如何实现PWM 输出,读者可自行查阅CC2530 中文手册)。定时器有一个很重要的概念:操作模式。操作模式包含:自由运行模式(free-running)、模模式(modulo)和 正计数/倒

android_Android –从图库中选择多张照片_cunfen6312的博客-程序员秘密

android 今天,我将讨论从照片库中选择多张照片的实现。 您知道,我已经进行了足够的搜索,以找到一种从android的本机库中选择多个图像的解决方案。 有两种方法可以在图库中实现多种图像选择:1)意图获取多个图像2)定义自定义图库,并从本地图库中获取并加载照片。 1.获取多张图像的意图: 作为本地恋人,我尝试通过使用以下代码实现与从图库中选择单个图像相同的解决方案,从而找到一种...

随便推点

微信公众平台接入指南_软件开发研究的博客-程序员秘密

接入微信公众平台开发,开发者需要按照如下步骤完成:1、填写服务器配置2、验证服务器地址的有效性3、依据接口文档实现业务逻辑下面详细介绍这3个步骤

python_字符_函数_weixin_30876945的博客-程序员秘密

一、字符集和字符编码1.定义  计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果。通俗的说,按照何种规则将字符存储在计算机中,如'a'用什么表示,称为"编码";反之,将存储在计算机中的二进制数解析显示出来,称为"解码",如同密码学中的加密和解密。在解码过程中,如果使用了错误的解码规则,则导致'a'解析成'b'或者乱码。字符(Chara...

解决CentOS8下安装MySQL 错误:没有任何匹配: mysql-community-server_LuminousHunter的博客-程序员秘密

解决CentOS8下安装MySQL 错误:没有任何匹配: mysql-community-server1.问题2.解决办法1.问题本次安装的是MySQL8.0 为例情况如下2.解决办法执行以下命令rpm -ivh mysql80-community-release-el8-1.noarch.rpm再去执行 就可以完成安装了注: 本文原创,转载请注明!!...

SVN安装及基本操作_疆~的博客-程序员秘密

目录1.SVN是什么版本控制是什么?为什么要使用SVN?2.Svn服务端和客户端获取方式服务端:https://www.visualsvn.com/server/download/客户端:https://tortoisesvn.net/downloads.html3.svn工作流程和架构图;3.1 svn工作方式:3.2 svn架构图:4.操作svn服务器的...

程序员如何精确评估开发时间?_枫哥和java的博客-程序员秘密

一个程序员能否精确评估开发时间,是一件非常重要的事情。如果你掌握了这项技能,你在别人的眼里就会是这样:靠谱经验十足对需求很了解延期风险小合格的软件工程师正规军,不是野路子评估开发时间的重...

推荐文章

热门文章

相关标签