在上一篇博文spring-boot如何得到一个tomcat实例(基于spring-boot_v1.5.14.RELEASE)中我们介绍了基于spring-boot 1.5.14版本中tomcat的实例化过程,由于2.0版本之后这个实例化过程发生了很大的改变,所以本文将以2.0.6版本为基础介绍tomcat的实例化过程。(https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/reference/htmlsingle/)
spring-boot加载tomcat的过程如下:
(1) springboot的主函数有一个注解 @SpringBootApplication,而这个注解里有一个@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration //开启自动配置
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
(2) 相比于1.x版本,2.x版本废弃了自动配置类EmbeddedServletContainerAutoConfiguration,而使用了ServletWebServerFactoryAutoConfiguration和EmbeddedWebServerFactoryCustomizerAutoConfiguration两个自动配置类,下面我们分别来介绍一下这两个autoConfiguration
(3) 我们先看一下比较简单的TomcatWebServerFactoryCustomizer吧
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
@Configuration
//默认使用tomcat,因此条件满足
@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {
// 实例化一个TomcatWebServerFactoryCustomizer实例bean,
//这个bean实现了WebServerFactoryCustomizer接口,
//它的customize方法负责对ConfigurableTomcatWebServerFactory进行配置
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
// 由于 Server.class, Loader.class, WebAppContext.class
//默认情况下不存在,因此JettyWebServerFactoryCustomizerConfiguration不会生效
@Configuration
@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
public static class JettyWebServerFactoryCustomizerConfiguration {
@Bean
public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new JettyWebServerFactoryCustomizer(environment, serverProperties);
}
}
// 由于Undertow.class, SslClientAuthMode.class默认情况下不存在,
// 因此UndertowWebServerFactoryCustomizerConfiguration不会生效
@Configuration
@ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
public static class UndertowWebServerFactoryCustomizerConfiguration {
@Bean
public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
}
}
}
(4)然后看一下 ServletWebServerFactoryAutoConfiguration
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
// 实例化一个 ServletWebServerFactoryCustomizer,它的泛型参数是ConfigurableServletWebServerFactory
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
// 实例化一个TomcatServletWebServerFactoryCustomizer,它的泛型参数是TomcatServletWebServerFactory
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
// 通过上面的@import引入
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;
}
//这边的处理跟v1.x版本是一致的,
//从beanFactory中获取一个WebServerFactoryCustomizerBeanPostProcessor实例bean,
//如果不存在,则主动new一个
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);
}
}
}
}
ServletWebServerFactoryCustomizer主要做了四件事:
// ServletWebServerFactoryCustomizer实现了WebServerFactoryCustomizer接口
// ConfigurableServletWebServerFactory继承了WebServerFactory接口
// 之所以强调这些,因为在 注4 总会用到哦
public class ServletWebServerFactoryCustomizer implements
WebServerFactoryCustomizer, Ordered {
private final ServerProperties serverProperties;
public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public int getOrder() {
return 0;
}
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(this.serverProperties::getPort).to(factory::setPort);
map.from(this.serverProperties::getAddress).to(factory::setAddress);
map.from(this.serverProperties.getServlet()::getContextPath)
.to(factory::setContextPath);
map.from(this.serverProperties.getServlet()::getApplicationDisplayName)
.to(factory::setDisplayName);
map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);
map.from(this.serverProperties::getSsl).to(factory::setSsl);
map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);
map.from(this.serverProperties::getCompression).to(factory::setCompression);
map.from(this.serverProperties::getHttp2).to(factory::setHttp2);
map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
map.from(this.serverProperties.getServlet()::getContextParameters)
.to(factory::setInitParameters);
}
// TomcatServletWebServerFactoryCustomizer实现了WebServerFactoryCustomizer接口
// TomcatServletWebServerFactory实现了WebServerFactory接口
// 在 注4 中会用到哦
public class TomcatServletWebServerFactoryCustomizer
implements WebServerFactoryCustomizer, Ordered {
private final ServerProperties serverProperties;
public TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public int getOrder() {
return 0;
}
@Override
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());
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// 当bean是WebServerFactory的实例时则进行postProcessBeforeInitialization处理
// 在注1中我们实例化了一个TomcatServletWebServerFactory,在这里可以派上用场了
//都是实现或继承了webServerFactory
if (bean instanceof WebServerFactory) {
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
// 使用WebServerFactoryCustomizer的customize方法对webServerFactory进行配置,
LambdaSafe
.callbacks(WebServerFactoryCustomizer.class, getCustomizers(),
webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
private Collection> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
// 对所有的WebServerFactoryCustomizer按照Orderd进行排序
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
// 从beanFactory中找到所有的WebServerFactoryCustomizer实例bean
// 步骤(3)中 EmbeddedWebServerFactoryCustomizerAutoConfiguration
//实例化了一个TomcatWebServerFactoryCustomizer的bean,
//这个bean实现了WebServerFactoryCustomizer接口,
// 在注2和注3中ServletWebServerFactoryAutoConfiguration实例化的
//ServletWebServerFactoryCustomizer和TomcatServletWebServerFactoryCustomizer
//都实现了WebServerFactoryCustomizer接口,
//因此在这里至少有3个我们已经知道的WebServerFactoryCustomizer可以在这里找到
private Collection> getWebServerFactoryCustomizerBeans() {
return (Collection) this.beanFactory
.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
对于上面的 注1~ 注4,都出现了WebServerFactory或它的子类,我们可以用下面这张类图来阐述他们的关系:TomcatServletWebServerFactory实现了ConfigurableTomcatWebServerFactory接口,而ConfigurableTomcatWebServerFactory接口又继承了WebServerFactory接口
(5) 跟1.x版本中的情况一样,以上步骤的主要目的就是实例化一个TomcatServletWebServerFactory,然后通过各个WebServerFactoryCustomizer对这个factory进行定制,最终得到一个完整的TomcatServletWebServerFactory,然后它的getWebServer方法就得到了一个tomcat实例,至此tomcat的实例过程讲解完毕。
最后我们再总结一下对于spring-boot v1.x版本和v2.x版本,tomcat的实例化过程的具体区别