【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));
		}
	}
相关推荐
JAVA坚守者7 分钟前
Tomcat 日志体系深度解析:从访问日志配置到错误日志分析的全链路指南
tomcat·日志分析·故障排查·服务器运维·访问日志·错误日志·生产环境优化
猴子请来的逗比4897 分钟前
tomcat搭建内网论坛
学习·tomcat
像风一样自由202035 分钟前
MQTT协议详解:物联网通信的轻量级解决方案
物联网·struts·servlet
秋野酱2 小时前
基于javaweb的SpringBoot爱游旅行平台设计和实现(源码+文档+部署讲解)
java·spring boot·后端
xlsw_3 小时前
servlet-api
servlet
Python ml3 小时前
Tomcat与纯 Java Socket 实现远程通信的区别
java·开发语言·tomcat
qq_12498707533 小时前
原生小程序+springboot+vue医院医患纠纷管理系统的设计与开发(程序+论文+讲解+安装+售后)
java·数据库·spring boot·后端·小程序·毕业设计
伊成3 小时前
一文详解Spring Boot如何配置日志
java·spring boot·单元测试
bing_1583 小时前
Spring Boot 的自动配置为 Spring MVC 做了哪些事情?
spring boot·spring·mvc
kaikaile19956 小时前
Jenkins集成Maven
servlet·jenkins·maven