本文共 11018 字,大约阅读时间需要 36 分钟。
概要
详细剖析ServletWebServerFactory实例化过程,整个过程使用多次后置处理对Bean实例化进行干预,完成TomcatServletWebServerFactory进行初始化
ServletWebServerFactory实例化
Spring容器在刷新容器的时候创建WebServer之前,先要创建ServletWebServerFactory
ServletWebServerFactory factory = getWebServerFactory();
从前面的自动配置类代码可以看出,要想得到TomcatServletWebServerFactory,得先实例化FactoryBean:EmbeddedTomcat
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
Spring在实例化TomcatServletWebServerFactory过程中会经过几次后置处理器的干预,它们分别是:
applyBeanPostProcessorsBeforeInitialization
这里面的CommonAnnotationPostProcessor对JSR-250@PostConstruct @PreDestroy处理
postProcessAfterInstantiation
postProcessProperties
postProcessPropertyValues
invokeInitMethods(类似后置处理器)
applyBeanPostProcessorsAfterInitialization
后置处理:applyBeanPostProcessorsBeforeInitialization
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization对servletWebServerFactory的处理
ApplicationContextAwareProcessor
因为TomcatServletWebServerFactory没有实现什么XxxAware接口,所以无需处理
WebApplicationContextServletContextAwareProcessor
是对ServletContextAware的处理,因为Spring自带的ApplicationContextAwareProcessor不包含ServletContextAware
ImportAwareBeanPostProcessor
ImportAwareBeanPostProcessor是ConfigurationClassPostProcessor的内部类,因为TomcatServletWebServerFactory没有实现什么ImportAware接口,所以无需处理
BeanPostProcessorChecker
BeanPostProcessorChecker是PostProcessorRegistrationDelegate的内部类,重写的postProcessBeforeInitialization方法本身不包含任何处理
ConfigurationPropertiesBindingPostProcessor
如果Bean被@ConfigurationProperties修饰,则使用该后置处理器将PropertySources与该Bean绑定
MethodValidationPostProcessor
它没有重写postProcessBeforeInitialization方法,而是他的抽象父类AbstractAdvisingBeanPostProcessor重写的,但是犯方法内并没有任何处理
WebServerFactoryCustomizerBeanPostProcessor
它完成了对TomcatServletWebServerFactory Bean(还不是完整的Spring Bean)的一些初始化操作
它的BeanDefinition由ServletWebServerFactoryAutoConfiguration完成注册,并在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors中完成实例化
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
/**
* 依次调用从容器中拿出来的WebServerFactoryCustomizer.customize方法
*/
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
getCustomizers()从自动配置类导入的BeanDefinitions当中找到WebServerFactoryCustomizer,并实例化
/**
* 从容器中拿WebServerFactoryCustomizer Bean,默认会拿出以下几个Customizer出来:
* TomcatWebSocketServletWebServerCustomizer来自于:WebSocketServletAutoConfiguration#webSocketServletWebServerCustomizer()
* ——实例化TomcatWebSocketServletWebServerCustomizer同时实例化WebSocketServletAutoConfiguration
* ServletWebServerFactoryCustomizer来自于:ServletWebServerFactoryAutoConfiguration#servletWebServerFactoryCustomizer()
* ——实例化ServletWebServerFactoryCustomizer同时实例化ServerProperties、ServletWebServerFactoryAutoConfiguration
* TomcatServletWebServerFactoryCustomizer来自于:ServletWebServerFactoryAutoConfiguration#tomcatServletWebServerFactoryCustomizer()
* ——实例化TomcatServletWebServerFactoryCustomizer
* TomcatWebServerFactoryCustomizer来自于:TomcatWebServerFactoryCustomizerConfiguration#tomcatWebServerFactoryCustomizer()
* ——实例化TomcatWebServerFactoryCustomizer同时实例化TomcatWebServerFactoryCustomizerConfiguration
* HttpEncodingAutoConfiguration$LocaleCharsetMappingsCustomizer来自于:HttpEncodingAutoConfiguration#localeCharsetMappingsCustomizer()
* ——实例化LocaleCharsetMappingsCustomizer同时实例化了HttpProperties、HttpEncodingAutoConfiguration
*/
private Collection> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
实例化这些Customizer之后,就要循环调用它们的customize方法对TomcatServletWebServerFactory进行初始化,比如添加ContextCustomer(Lamda表达式),设置Server和Context的核心参数等等
TomcatWebSocketServletWebServerCustomizer
public void customize(TomcatServletWebServerFactory factory) {
//给TomcatServletWebServerFactory添加ContextCustomizer
factory.addContextCustomizers((context) -> context.addApplicationListener(WsContextListener.class.getName()));
}
在获取TomcatWebServer的时候会使用添加的ContextCustomizer,代码如下
TomcatServletWebServerFactory#configureContext(
/**
* 使用TomcatServletWebServerFactory准备好的参数配置TomcatEmbeddedContext
*/
protected void configureContext(Context context, ServletContextInitializer[] initializers) {
TomcatStarter starter = new TomcatStarter(initializers);
if (context instanceof TomcatEmbeddedContext) {
TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;
embeddedContext.setStarter(starter);
embeddedContext.setFailCtxIfServletStartFails(true);
}
/**
* 将当前ApplicationContext的initializer与TomcatEmbeddedContext绑定
*/
context.addServletContainerInitializer(starter, NO_CLASSES);
for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
context.addLifecycleListener(lifecycleListener);
}
for (Valve valve : this.contextValves) {
context.getPipeline().addValve(valve);
}
for (ErrorPage errorPage : getErrorPages()) {
new TomcatErrorPage(errorPage).addToContext(context);
}
for (MimeMappings.Mapping mapping : getMimeMappings()) {
context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
}
configureSession(context);
new DisableReferenceClearingContextCustomizer().customize(context);
/**
* 使用在实例化TomcatServletWebServerFactory时添加的ContextCustomizer改变TomcatEmbeddedContext状态
*/
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
customizer.customize(context);
}
}
ServletWebServerFactoryCustomizer
public void customize(ConfigurableServletWebServerFactory factory) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
//设置端口:8080
map.from(this.serverProperties::getPort).to(factory::setPort);
//设置地址,比如:localhost
map.from(this.serverProperties::getAddress).to(factory::setAddress);
//设置ContextPath,比如:www.xxx.com/ContextPath/
map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath);
//设置应用名称
map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName);
//设置Session
map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);
//设置SSL
map.from(this.serverProperties::getSsl).to(factory::setSsl);
//设置JSP,用以支持JSP SERVLET
map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);
map.from(this.serverProperties::getCompression).to(factory::setCompression);
//设置HTTP2,用以支持HTTP/2
map.from(this.serverProperties::getHttp2).to(factory::setHttp2);
//设置Header
map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
//设置初始化参数
map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);
}
TomcatServletWebServerFactoryCustomizer
public void customize(TomcatServletWebServerFactory factory) {
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
if (!ObjectUtils.isEmpty(tomcatProperties.getAdditionalTldSkipPatterns())) {
factory.getTldSkipPatterns().addAll(tomcatProperties.getAdditionalTldSkipPatterns());
}
//是否支持使用"/"重定向到根路径
if (tomcatProperties.getRedirectContextRoot() != null) {
customizeRedirectContextRoot(factory, tomcatProperties.getRedirectContextRoot());
}
//是否支持相对或者绝对路径的重定向
if (tomcatProperties.getUseRelativeRedirects() != null) {
customizeUseRelativeRedirects(factory, tomcatProperties.getUseRelativeRedirects());
}
}
TomcatWebServerFactoryCustomizer
/**
* 设置容器的相关核心参数,比如Basedir,最大最小线程数等等
*/
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::getMaxThreads).when(this::isPositive)
.to((maxThreads) -> customizeMaxThreads(factory, tomcatProperties.getMaxThreads()));
propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
。。。省略部分代码。。。
//添加关于Resource的ContextCustomizer
customizeStaticResources(factory);
//添加一个功能是"错误日志报告Valve"的ContextCustomizer,如果看过Tomcat源码,它自己也有这么一个类似的ErrorReportValve
customizeErrorReportValve(properties.getError(), factory);
}
LocaleCharsetMappingsCustomizer
/**
* 设置本地字符集
*/
public void customize(ConfigurableServletWebServerFactory factory) {
if (this.properties.getMapping() != null) {
factory.setLocaleCharsetMappings(this.properties.getMapping());
}
}
ErrorPageRegistrarBeanPostProcessor
完成默认错误页的相关注册工作
private void postProcessBeforeInitialization(ErrorPageRegistry registry) {
/**
* 调用getRegistrars()实例化ErrorPageCustomizer implements ErrorPageRegistrar,SpringBoot自动配置类ErrorMvcAutoConfiguration完成的ErrorPageCustomizer配置
* 往TomcatServletWebServerFactory中添加了一个path="/error"的ErrorPage
*/
for (ErrorPageRegistrar registrar : getRegistrars()) {
registrar.registerErrorPages(registry);
}
}
CommonAnnotationBeanPostProcessor
调用它父类的postProcessBeforeInitialization,在这会调用被@PostConstruct注解修饰的方法。它还有另外一个功能就是调用被@PreDestroy修饰的方法
不过TomcatServletWebServerFactory并没有
AutowiredAnnotationBeanPostProcessor
本身不包含任何处理
ApplicationListenerDetector
本身不包含任何处理
调用afterPropertiesSet方法invokeInitMethods
调用接口InitializingBean接口实现类的afterPropertiesSet方法
很遗憾,TomcatServletWebServerFactory并没有实现InitializingBean接口
applyBeanPostProcessorsAfterInitialization
接下来又像applicationBeanPostProcessorsBeforInitialization一样,循环11个PostProcessor
ApplicationContextAwareProcessor
本身不包含任何处理
WebApplicationContextServletContextAwareProcessor
本身不包含任何处理
ImportAwareBeanPostProcessor
本身不包含任何处理
BeanPostProcessorChecker
这个类可以不关注它,是用来校验Bean理论上应该被多少BeanPostProcessor处理与实际数量是否一致,如果不一致就会答应日志,提示没有被所有符合条件的PostProcessor处理
ConfigurationPropertiesBindingPostProcessor
本身不包含任何处理
MethodValidationPostProcessor
TomcatServletWebServerFactory不是它的处理对象,该Processor和AOP相关:使Spring AOP Advisor作用到指定的特殊 bean上
WebServerFactoryCustomizerBeanPostProcessor
本身不包含任何处理
ErrorPageRegistrarBeanPostProcessor
本身不包含任何处理
CommonAnnotationBeanPostProcessor
本身不包含任何处理
AutowiredAnnotationBeanPostProcessor
本身不包含任何处理
ApplicationListenerDetector
TomcatServletWebServerFactory不是它的处理对象,该Processor可以将一个实现了ApplicationListener接口的类对应的Bean添加到容器的ApplicationListener列表中。Spring的又一个扩展点
小结
梳理完这个过程,把Spring实例化Bean的主要过程又走了一遍,复习复习也好。但是关于
postProcessAfterInstantiation:实例化后置处理
postProcessProperties:在postProcessAfterInstantiation执行之后并返回true, 返回的PropertyValues将作用于给定bean属性赋值(applyPropertyValues()). spring 5.1之后出现以替换@Deprecated标注的postProcessPropertyValues
总结
如果真的把SpringBoot所有自动配置类如何配置与实例化都看完,这个工作量真的好大。。。。决定把Tomcat这块整完后,如果有时间再把DispatcherServlet实例化过程梳理完,就暂停SpringBoot源码分析了。以后遇到情况或者有时间再补充,接下来还要看其它的。
TomcatServletWebServerFactory实例化只是Tomcat 初始化阶段的一个对象,在这里准备好了Server Context相关的参数等。通过看它的实例化过程加深了Spring Bean实例化过程。
转载地址:https://blog.csdn.net/weixin_33303537/article/details/115781910 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!