springBoot 默认使用的是tomcat
在导入的依赖中:autoconfigure 中的web 目录下所有含有Server的类都与Servlet容器的相关
笔记的原理分析基于Spring Boot2.1.3版本;2.0 以下版本的一些类被代替
有三个:EmbeddedUndertow ,EmbeddedJetty,EmbeddedTomcat @Conditionalxxx 标注的类;条件满足才向容器中添加组件
例如:添加tomcat
@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
@ConditionalOnMissingBean(
value = {ServletWebServerFactory.class},
search = SearchStrategy.CURRENT
)
public static class EmbeddedTomcat {
public EmbeddedTomcat() {
}
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
重要注解详解:
1. @ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
容器中存在servlet.class(存在servlet依赖) tomcat.class(tomcat依赖) 才能执行向容器中添加组件
2. @ConditionalOnMissingBean(value = {ServletWebServerFactory.class},search = SearchStrategy.CURRENT )
判断容器中没有用户自定义的ServletWeServerbFactory
ServletWebServerFactory
嵌入式Servlet工厂;作用:创建嵌入式Servlet容器
容器工厂:
继承树
当中只有一个方法:获取嵌入式Servlet容器 (WebServer)
public interface ServletWebServerFactory {
WebServer getWebServer(ServletContextInitializer... var1);
}
容器工厂包含了:TomcatServletWebServerFactory,JettyServletWebServerFactory,UndetowServletWebServerFactory
webServr 嵌入式Servlet容器:
继承树
在判断@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})是否导入依赖,满足条件: return new TomcatServletWebServerFactory(); 添加对应的Servlet容器工厂;通过工厂的唯一方法getWebServer 获取对应的Servlet容器TomcatServer
;
TomcatServletWebServerFactory
tomcat 的容器工厂
在工厂中获取tomcat 的方法:getWebServer
public WebServer getWebServer(ServletContextInitializer... initializers) {
1. 创建Tomcat对象
Tomcat tomcat = new Tomcat();
File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
2.完成tomct 配置的基本操作
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
this.customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
this.configureEngine(tomcat.getEngine());
Iterator var5 = this.additionalTomcatConnectors.iterator();
while(var5.hasNext()) {
Connector additionalConnector = (Connector)var5.next();
tomcat.getService().addConnector(additionalConnector);
}
this.prepareContext(tomcat.getHost(), initializers);
3.将tomcat 传入方法:getTomcatWebServer()
return this.getTomcatWebServer(tomcat);
}
getTomcatWebServer()
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, this.getPort() >= 0); 端口>0 就创建Tomcat 容器
}
TomcatWebServer
对应的构造函数:在TomcatWebServer 中
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
this.monitor = new Object();
this.serviceConnectors = new HashMap();
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart; 自动启动变量
this.initialize();
}
方法:initialize()核心代码:
this.tomcat.start(); 启动Tomcat
至此Tomcat就完成了配置和自动启动
修改定制Servlet 容器的方法:
配置文件和ServerProperties 绑定/修改定制组件 WebServerFactoryCustomizer
他们的本质是一样的:在ServletWebServerFactoryAutoConfiguration配置类中@EnableConfigurationProperties({ServerProperties.class})
导入了:BeanPostProcessorsRegistrar
;在这个类的方法中添加了组件WebServerFactoryCustomizerBeanPostProcessor
定制器后置处理器
也就是说一旦容器中添加任何组件都会启动定制后置处理器,进行Servlet的赋值
后置处理器起作用的过程:
在初始化之前:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
如果组件创建的对象是:WebServerFactory 就调用postProcessBeforeInitialization
if (bean instanceof WebServerFactory) {
this.postProcessBeforeInitialization((WebServerFactory)bean);
}
return bean;
}
解释:
自定义定制器:
@Bean
public WebServerFactoryCustomizer MyCustomizer(){
return new WebServerFactoryCustomizer() {... }
}
public interface WebServerFactoryCustomizer {
void customize(T var1);
}
ConfigurableWebServerFactory继承WebServerFactory ;所以修改数据的时候创建了WeServerFactory
自动配置的时候也会创建对应的工厂对象
postProcessBeforeInitialization
核心语句:
customizer.customize(webServerFactory);
获取spring Boot中所有的WebServerFactoryCustomizer 这个类型的定制器通过定制方法:customize()给Servlet容器赋值
同时这也是为什么自定义修改配置组件是自定义的WebServerFactoryCustomizer
在这个配置类中:
private final ServerProperties serverProperties;
同时使用了:
public void customize(ConfigurableServletWebServerFactory factory) {
完成了Tomcat的各项配置的修改和定制
使用修改定制器 webServerFactoryCustomizer
创建了ConfigurableWebServerFactory 对象
,触发WebServerFactoryCustomizerBeanPostProcessor
后置处理器,判断是否为WebServerFactory
类型;
ConfiurableWebServerFactory 继承webServerFactory
满足条件,就会获取容器中的所有定制器(customizer.cutomize(bean)),为Servlet容器修改和定制配置【相关的配置类ServletWebServerFactoryAutoConfiguration;导入了定制处理器】
使用配置文件application.propertoes 修改配置。server 相关的配置修改是与ServerProperties 类绑定的,所以相关的修改会直接通过Serverproperties 的方法实现【相关的配置类:ServletWebServerFactoryCustomizer】
触发后置处理器
,配置类中:@EnableConfigurationProperties({ServerProperties.class})
根据配置文件,获取所有的定制器为Sevlet容器赋值