SpringBoot学习-part32嵌入式Servlet容器的自动配以及初始化

createWebServer

SpringBoot 会从ServletWebServerApplicationContext 中启动 createWebServer 方法,该方法会根据当前导入的Servlet类型创建相应的ServletWeb服务工厂:Jetty、Tomcat 或 Undertow。
为啥这里没有Netty?
在这里插入图片描述

private void createWebServer() {
	WebServer webServer = this.webServer;
	ServletContext servletContext = getServletContext();
	if (webServer == null && servletContext == null) {
		ServletWebServerFactory factory = getWebServerFactory();
		this.webServer = factory.getWebServer(getSelfInitializer());
		getBeanFactory().registerSingleton("webServerGracefulShutdown",
				new WebServerGracefulShutdownLifecycle(this.webServer));
		getBeanFactory().registerSingleton("webServerStartStop",
				new WebServerStartStopLifecycle(this, this.webServer));
	}
	else if (servletContext != null) {
		try {
			getSelfInitializer().onStartup(servletContext);
		}
		catch (ServletException ex) {
			throw new ApplicationContextException("Cannot initialize servlet context", ex);
		}
	}
	initPropertySources();
}

在这里插入图片描述
创建tomcatServer

在这里插入图片描述如何获取getWebServerFactory?

这里的要get的Bean名字为:tomcatServletWebServerFactory
在这里插入图片描述由于tomcatServletWebServerFactory必然为单例,首次get时必然需要create
在这里插入图片描述

try {
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	if (logger.isTraceEnabled()) {
		logger.trace("Finished creating instance of bean '" + beanName + "'");
	}
	return beanInstance;
}

create之后需要初始化

在这里插入图片描述

try {
	populateBean(beanName, mbd, instanceWrapper);
	exposedObject = initializeBean(beanName, exposedObject, mbd);
}

在AbstractAutowireCapableBeanFactory类中:

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
	//调用初始方法的前置处理器
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
	//调用初始化方法
	invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
	throw new BeanCreationException(
			(mbd != null ? mbd.getResourceDescription() : null),
			beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
	//初始化方法的后置处理
	wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

在调用初始化器的前置方法期间,需要获得并调用tomcatWebServerFactoryCustomizer,即tomcat网络服务器工厂的定制化器。

在这里插入图片描述初次尝试Get必然失败需要Creat 这个定制化器。

在EmbeddedWebServerFactoryCustomizerAutoConfiguration 类中调用如下方法:

/**
	 * Nested configuration if Tomcat is being used.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
	public static class TomcatWebServerFactoryCustomizerConfiguration {

		@Bean
		public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment,
				ServerProperties serverProperties) {
			return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

在这里插入图片描述使用合并后的后置处理器来修饰这个定制器(tomcatWebServerFactoryCustomizer)

在这里插入图片描述

来到WebServerFactoryCustomizerBeanPostProcessor类中的初始化方法前置处理器

private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
	LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
			.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
			.invoke((customizer) -> customizer.customize(webServerFactory));
}

在这里插入图片描述

customize方法定制化webServerFactory

这个处理器会调用定制化器的customize方法定制化webServerFactory:

@Override
public void customize(ConfigurableTomcatWebServerFactory factory) {
	ServerProperties properties = this.serverProperties;
	ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
	PropertyMapper propertyMapper = PropertyMapper.get();
	propertyMapper.from(tomcatProperties::getBasedir).whenNonNull().to(factory::setBaseDirectory);
	propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull().as(Duration::getSeconds)
			.as(Long::intValue).to(factory::setBackgroundProcessorDelay);
	customizeRemoteIpValve(factory);
	ServerProperties.Tomcat.Threads threadProperties = tomcatProperties.getThreads();
	propertyMapper.from(threadProperties::getMax).when(this::isPositive)
			.to((maxThreads) -> customizeMaxThreads(factory, threadProperties.getMax()));
	propertyMapper.from(threadProperties::getMinSpare).when(this::isPositive)
			.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
	propertyMapper.from(this.serverProperties.getMaxHttpHeaderSize()).whenNonNull().asInt(DataSize::toBytes)
			.when(this::isPositive)
			.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize));
	propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull().asInt(DataSize::toBytes)
			.to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
	propertyMapper.from(tomcatProperties::getMaxHttpFormPostSize).asInt(DataSize::toBytes)
			.when((maxHttpFormPostSize) -> maxHttpFormPostSize != 0)
			.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
	propertyMapper.from(tomcatProperties::getAccesslog).when(ServerProperties.Tomcat.Accesslog::isEnabled)
			.to((enabled) -> customizeAccessLog(factory));
	propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull().to(factory::setUriEncoding);
	propertyMapper.from(tomcatProperties::getConnectionTimeout).whenNonNull()
			.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
	propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)
			.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
	propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)
			.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
	propertyMapper.from(tomcatProperties::getProcessorCache)
			.to((processorCache) -> customizeProcessorCache(factory, processorCache));
	propertyMapper.from(tomcatProperties::getRelaxedPathChars).as(this::joinCharacters).whenHasText()
			.to((relaxedChars) -> customizeRelaxedPathChars(factory, relaxedChars));
	propertyMapper.from(tomcatProperties::getRelaxedQueryChars).as(this::joinCharacters).whenHasText()
			.to((relaxedChars) -> customizeRelaxedQueryChars(factory, relaxedChars));
	customizeStaticResources(factory);
	customizeErrorReportValve(properties.getError(), factory);
}

在这里插入图片描述

webServerFactory定制化=webServer定制化

这个webServerFactory实现了ServletWebServerFactory的getWebServer方法:
在这里插入图片描述
所以可通过实现WebServerFactoryCustomizer接口的方式,实现customize方法来修饰tomcatServer

启动流程总结:

  1. SpringBoot 根据到导入的依赖信息,自动创建相应的webServerFactoryCustomizer(工厂定制器)

  2. web服务工厂定制器的后置处理器类中的方法会收集所有实现了webServerFactoryCustomizer接口的定制器,并依次调用这些定制器的customize方法,去定制化servlet容器工厂。

  3. 嵌入式的Servlet容器工厂调用getWebServer方法创建tomcat容器(tomcatServer),初始化容器。

定制化总结:

  1. 由于Customizer的大量信息都是从Properties中加载的,因此可以通过修改全局配置文件application.properties,来达到定制化的目的。

  2. 可以实现WebServerFactoryCustomizer接口,并重写其customize方法达到定制化目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值