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

自动装配加载 ServletWebServerFactoryAutoConfiguration

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

java 复制代码
@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
	 */
	@Bean
	public 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;

		@Override
		public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
			if (beanFactory instanceof ConfigurableListableBeanFactory) {
				this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
			}
		}

		@Override
		public 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的创建。

java 复制代码
	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 hierarchy
	String[] 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对象

java 复制代码
	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添加connector
		tomcat.getService().addConnector(connector);
		// 定制自己的连接器
		customizeConnector(connector);
		// 设置到tomcat中
		tomcat.setConnector(connector);
		// 自动部署 false
		tomcat.getHost().setAutoDeploy(false);
		configureEngine(tomcat.getEngine()); // 配置Engine
		for (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();

	// 启动tomcat
	protected void finishRefresh() {
		super.finishRefresh();
		WebServer webServer = startWebServer();
		if (webServer != null) {
			publishEvent(new ServletWebServerInitializedEvent(webServer, this));
		}
	}
相关推荐
一 乐18 分钟前
博客管理系统|基于springboot + vue博客管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕设
王闯写bug38 分钟前
tomcat老版本下载tomcat8.5下载
java·tomcat
凤山老林43 分钟前
Spring Boot DDD 分层架构落地:领域模型、聚合根与事件驱动的业务实战
java·spring boot·架构
马剑威(威哥爱编程)1 小时前
【AI全栈后端12-03】Spring Boot 用多模型路由把智能客服成本降下来
java·人工智能·spring boot
樱花落木兰2 小时前
SpringBoot + ECharts 后台数据统计报表模块实战
java·javascript·spring boot·ai·log4j·github·echarts
CarIise3 小时前
Spring Boot入门:从项目创建到请求响应实战
spring boot
马剑威(威哥爱编程)4 小时前
【AI全栈后端12-02】Spring Boot 跑通第一个 AI 对话接口:HR 政策问答机器人实战
java·人工智能·spring boot·机器人
摇滚侠4 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC 容器的高级机制 编程式驱动 IOC 阅读笔记 7
java·spring boot·笔记
白帽攻防录5 小时前
SRC 挖洞:Apache Tomcat 加密拦截器绕过深度复盘,CVE-2026-34486 fail-open 一行代码怎么打穿集群通信
java·网络安全·tomcat·apache
不停喝水5 小时前
【前端转全栈java速通课】 项目实战④-1 Spring Boot 创建项目-定义接口-请求参数处理-分层规范-依赖注入
java·前端·spring boot