spring boot
spring boot 可以通过java -jar的形式来启动web容器并且启动应用,其背后也使用到了自动配置
TomcatServletWebServerFactory用来产生TomcatServletWebServer
TomcatServletWebServer则用来管来tomcat容器的启停
ServletWebServerFactoryAutoConfiguration
ServletWebServerFactoryAutoConfiguration就是用来进行ServletWebServerFactory的自动配置的
// 当前类是一个配置类
@Configuration(proxyBeanMethods = false)
// 指定自动配置的优先级
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
// 只有类路径中存在ServletRequest时,才进行加载
@ConditionalOnClass(ServletRequest.class)
// 当应用类型是servlet时才进行加载
@ConditionalOnWebApplication(type = Type.SERVLET)
// 读取配置到ServerProperties中
@EnableConfigurationProperties(ServerProperties.class)
// 导入下面几个类
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
}
ServletWebServerFactoryConfiguration.EmbeddedTomcat
EmbeddedTomcat主要的作用就是创建一个TomcatServletWebServerFactory ,并且配置化,然后注入到容器中
// 是一个配置类
@Configuration(proxyBeanMethods = false)
// 当类路径中有Servlet,Tomcat和UpgradeProtocol时才加载
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
// 当没有类型为ServletWebServerFactory的bean时才加载
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedTomcat {
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
// 用来定制connector
factory.getTomcatConnectorCustomizers()
.addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
// 用来定制context
factory.getTomcatContextCustomizers()
.addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
// 用来定制protocolHandler
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}
BeanPostProcessorsRegistrar
主要用来注册两个beanpostprocessor:WebServerFactoryCustomizerBeanPostProcessor和ErrorPageRegistrarBeanPostProcessor
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;
}
// 这里会检测当前容器中是否存在指定类型的bean,如果不存在会注册一个,并且使用指定的bean name
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);
}
}
}
WebServerFactoryCustomizerBeanPostProcessor
这个bean post processor的主要作用是从容器中获取WebServerFactoryCustomizer类型的bean,然后对容器中的WebServerFactory进行处理
public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<WebServerFactoryCustomizer<?>> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"WebServerCustomizerBeanPostProcessor can only be used with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 对WebServerFactory进行处理
if (bean instanceof WebServerFactory) {
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
// 从容器中获取WebServerFactoryCustomizer类型的bean,然后调用customize方法,对WebServerFactory进行处理
LambdaSafe.callbacks( .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
// 从beanFactory中获取WebServerFactoryCustomizer类型的bean
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
return (Collection) this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
}
ErrorPageRegistrarBeanPostProcessor
这个bean post processor的主要作用是用来将容器中的ErrorPageRegistrar注册到ErrorPageRegistry
public class ErrorPageRegistrarBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<ErrorPageRegistrar> registrars;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"ErrorPageRegistrarBeanPostProcessor can only be used with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 对ErrorPageRegistry进行处理
if (bean instanceof c) {
postProcessBeforeInitialization((ErrorPageRegistry) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
private void postProcessBeforeInitialization(ErrorPageRegistry registry) {
// 从容器中获取ErrorPageRegistrar类型的bean,然后注册到ErrorPageRegistry中
for (ErrorPageRegistrar registrar : getRegistrars()) {
registrar.registerErrorPages(registry);
}
}
private Collection<ErrorPageRegistrar> getRegistrars() {
if (this.registrars == null) {
// Look up does not include the parent context
this.registrars = new ArrayList<>(
this.beanFactory.getBeansOfType(ErrorPageRegistrar.class, false, false).values());
this.registrars.sort(AnnotationAwareOrderComparator.INSTANCE);
this.registrars = Collections.unmodifiableList(this.registrars);
}
return this.registrars;
}
}
其他bean
在ServletWebServerFactoryAutoConfiguration中还有以下三个bean
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
ServletWebServerFactoryCustomizer
上面分析过WebServerFactoryCustomizerBeanPostProcessor这个bean post processor会对WebServerFactory进行处理,使用WebServerFactoryCustomizer对WebServerFactory进行定制
ServletWebServerFactoryCustomizer就继承了WebServerFactoryCustomizer
主要的作用就是使用配置文件中server为前缀的配置,然后使用这些配置对WebServerFactory进行定制
public class ServletWebServerFactoryCustomizer
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
private final ServerProperties serverProperties;
public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
// ServerProperties会读取配置文件中server为前缀的配置
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()::isRegisterDefaultServlet).to(factory::setRegisterDefaultServlet);
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);
map.from(this.serverProperties.getShutdown()).to(factory::setShutdown);
}
}
TomcatServletWebServerFactoryCustomizer
主要是用配置文件中tomcat相关的配置对WebServerFactory进行配置
public class TomcatServletWebServerFactoryCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>, Ordered {
private final ServerProperties serverProperties;
public TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public int getOrder() {
return 0;
}
@Override
public void customize(TomcatServletWebServerFactory factory) {
// 读取配置文件中tomcat相关的配置
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
if (!ObjectUtils.isEmpty(tomcatProperties.getAdditionalTldSkipPatterns())) {
factory.getTldSkipPatterns().addAll(tomcatProperties.getAdditionalTldSkipPatterns());
}
if (tomcatProperties.getRedirectContextRoot() != null) {
customizeRedirectContextRoot(factory, tomcatProperties.getRedirectContextRoot());
}
customizeUseRelativeRedirects(factory, tomcatProperties.isUseRelativeRedirects());
factory.setDisableMBeanRegistry(!tomcatProperties.getMbeanregistry().isEnabled());
}
private void customizeRedirectContextRoot(ConfigurableTomcatWebServerFactory factory, boolean redirectContextRoot) {
factory.addContextCustomizers((context) -> context.setMapperContextRootRedirectEnabled(redirectContextRoot));
}
private void customizeUseRelativeRedirects(ConfigurableTomcatWebServerFactory factory,
boolean useRelativeRedirects) {
factory.addContextCustomizers((context) -> context.setUseRelativeRedirects(useRelativeRedirects));
}
}
Web容器的创建
我们知道在spring boot 应用启动过程中,会刷新容器,调用生成的ApplicationContext的refresh方法
如果是Servlet应用,创建的ApplicationContext是ServletWebServerApplicationContext类型的
这里看下ServletWebServerApplicationContext的refresh方法
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
可以看到会调用父类AbstractApplicationContext的refresh方法,refresh方法内部会调用onRefresh,AbstractApplicationContext的onRefresh是一个空的实现,所以逻辑在子类中
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 省略
// Initialize other special beans in specific context subclasses.
onRefresh();
// 省略
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
下面返过来看下ServletWebServerApplicationContext的onRefresh方法,会创建一个webserver
protected void onRefresh() {
super.onRefresh();
try {
// 创建一个webserver
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
// 第一次进入的时候,webservert和servletcontext都是null
if (webServer == null && servletContext == null) {
// 从容器中获取ServletWebServerFactory类型的bean
ServletWebServerFactory factory = getWebServerFactory();
// 通过factory来获取容器对象
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();
}
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
// 设置baseDir
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
// 设置connector
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
// 对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容器
return getTomcatWebServer(tomcat);
}