文章目录
Spring Boot Tomcat启动原理源码分析
Spring Boot应用程序在启动时,执行ServletWebServerApplicationContext的onRefresh方法时,会从IOC容器中获取ServletWebServerFactory对象创建ServletWebServer。
ServletWebServerFactory是如何注册到Spring IOC中的,因spring-boot-autoconfigure中的spring.factories文件中配置了ServletWebServerFactoryAutoConfiguration,Spring Boot启动时会自动注册该配置类,该配置类中标注了ConditionalOnClass和ConditionalOnWebApplication注解,表示该应用程序是Servlet类型的应用时,该配置类才会被启用。EnableConfigurationProperties注解用于开启server配置属性自动装配。通过Import注解导入ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar(该类的作用在后续进行分析)和Spring Boot支持的Servlet容器配置类(EmbeddedTomcat、EmbeddedJetty、EmbeddedUndertow)。
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)//需要Servlet才启用
@ConditionalOnWebApplication(type = Type.SERVLET)//需要Servlet才启用
@EnableConfigurationProperties(ServerProperties.class)//开启server属性自动装配
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
//代码略
}
EmbeddedTomcat源码分析
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })//当前类路径存在Servlet、Tomcat、UpgradeProtocol类时,才会启用
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)//当前IOC容器中未配置ServletWebServerFactory时,才会启动
static class EmbeddedTomcat {
//配置TomcatServletWebServerFactory,用于创建tomcat
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
//配置自定义参数
factory.getTomcatConnectorCustomizers()
.addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers()
.addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}
TomcatServletWebServerFactory源码分析
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
//创建tomcat
//spring boot 启动时ServletWebServerApplicationContext执行onRefresh方法时,会调用该方法
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
//创建tomcat实例
Tomcat tomcat = new Tomcat();
//设置tomcat运行基础参数
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);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
//配置tomcat engine
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
//创建tomcat web server
return getTomcatWebServer(tomcat);
}
省略部分代码...
}
在执行getTomcatWebServer方法时,TomcatServletWebServerFactory会创建TomcatWebServer对象
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
}
创建TomcatWebServer对象时,在构造方法中会调用该类的initialize方法启动tomcat
public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
//调用TomcatWebServer的初始化方法,启动tomcat
initialize();
}
private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try {
addInstanceIdToEngineName();
Context context = findContext();
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// happen when the service is started.
removeServiceConnectors();
}
});
// 启动tomcat
// Start the server to trigger initialization listeners
this.tomcat.start();
// We can re-throw failure exception directly in the main thread
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
startDaemonAwaitThread();
}
catch (Exception ex) {
stopSilently();
destroySilently();
throw new WebServerException("Unable to start embedded Tomcat", ex);
}
}
}
ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar
执行invokeBeanFactoryPostProcessors方法时,会调用ConfigurationClassPostProcessor对象的方法对所有配置类进行解析,在解析过程中会读取ImportBeanDefinitionRegistrar的registerBeanDefinitions方法进行bean注册
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;
}
}
//在refresh方法中执行invokeBeanFactoryPostProcessors时调用
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
//注册WebServerFactoryCustomizerBeanPostProcessor
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
//注册ErrorPageRegistrarBeanPostProcessor
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);
//设置为true,在spring实例化bean时,会不执行beanPostProcessor的逻辑
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}