SpringBoot中是由ServletWebServerFactoryAutoConfiguration来完成对Servlet容器的配置,下面是它的源码解析:
首先来分析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 {
关注最关键的两个注解EnableConfigurationProperties和Import
- @EnableConfigurationProperties:启用ServerProperties这个类中的配置属性,ServerProperties会先实例化注入IOC容器中;ServerProperties在实例化时会将配置文件中有关server的配置信息对自己的属性进行赋值。
- @Import:导入外部配置,包括内部类BeanPostProcessorsRegistrar(后置处理器)。EmbeddedTomcat,EmbeddedJetty,EmbeddedUndertow这三个属于ServletWebServerFactoryConfiguration 的嵌套配置类,这三个配置类会分别检测classpath上存在的类,从而判断当前应用使用的是 Tomcat/Jetty/Undertow,从而决定定义哪一个 Servlet Web服务器的工厂 bean。
下面来分析ServletWebServerFactoryAutoConfiguration类中各方法的作用。
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
向IOC容器中注入ServletWebServerFactoryCustomizer (自定义Servlet Web服务工厂),该类根据serverProperties中的属性创建,ServletWebServerFactoryCustomizer在Servlet容器进行属性赋值有着很大的最用。
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
针对当前Servlet容器是Tomcat时定义该 bean,用于定制化TomcatServletWebServerFactory
最后还有一段内部类BeanPostProcessorsRegistrar的源码,留到后面再分析它的作用。
下面来分析导入配置类。
EmbeddedTomcat(与EmbeddedJetty,EmbeddedUndertow相似)
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
EmbeddedTomcat是ServletWebServerFactoryConfiguration的内部类,EmbeddedTomcat只会在类路径下存在Servlet,Tomcat,UpgradeProtocol的情况下,并且在IOC容器中没有ServletWebServerFactory类的情况下才会初始化。
EmbeddedTomcat内部的方法tomcatServletWebServerFactory会向IOC容器中注入TomcatServletWebServerFactory 。
TomcatServletWebServerFactory类中getWebServer方法便是获取Servlet容器的关键,下面是它的源码
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
//创建tomcat容器
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
//配置tomcat容器
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
//将初始化的tomcat传入,返回一个TocmatWebServer
return getTomcatWebServer(tomcat);
}
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0);
}
对于Servlet嵌入式容器的自定义配置,一种是外部配置文件,在上面ServletWebServerFactoryAutoConfiguration的ServletWebServerFactoryCustomizer方法上传入serverProperties,另外一种向IOC容器中注入自己的WebServerFactoryCustomizer,在实现它的方法内设置,那么WebServerFactoryCustomizer是如何生效的呢?
该类的生效就来自于还未分析的BeanPostProcessorsRegistrar。
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
...
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
//向容器中注册webServerFactoryCustomizerBeanPostProcessor
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class);
}
...
}
WebServerFactoryCustomizerBeanPostProcessor这个类是对Servlet容器配置的关键
public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
...
@Override
//在容器工厂初始化之前
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//如果当前初始化的是WebServerFactory类型的组件
if (bean instanceof WebServerFactory) {
//调用下面postProcessBeforeInitialization的方法
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
//获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
//从容器中获取所有WebServerFactoryCustomizer的组件
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
...
}
总结
Servlet容器自动配置:
- SpringBoot根据导入的依赖情况,给容器中添加相应的ServletWebServerFactory,如TomcatServletWebServerFactory
- 在创建Servlet容器工厂前触发BeanPostProcessorsRegistrar向容器注入WebServerFactoryCustomizerBeanPostProcessor;只要是嵌入式的Servlet容器工厂,就会触发;
- WebServerFactoryCustomizerBeanPostProcessor从容器中获取所有的WebServerFactoryCustomizer,调用定制器的定制方法;