Springboot内嵌Tomcat启动流程源码分析

又是美好的一天呀~
个人博客地址: huanghong.top

本文预估阅读时长为15分钟左右~

往下看看~

  • Springboot内嵌Tomcat启动流程源码分析
    • ServletWebServerFactoryAutoConfiguration
    • 应用启动执行至上下文刷新
    • onRefresh
    • createWebServer
    • getWebServerFactory
    • getWebServer
    • customizeConnector
    • getTomcatWebServer
    • TomcatWebServer
    • initialize
    • startDaemonAwaitThread
    • 扩展jetty容器配置

Springboot内嵌Tomcat启动流程源码分析

ServletWebServerFactoryAutoConfiguration

org\springframework\boot\spring-boot-autoconfigure\2.6.6\spring-boot-autoconfigure-2.6.6.jar!\META-INF\spring.factories

//ServletWebServerFactoryConfiguration.EmbeddedTomcat.class
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedTomcat {
   //构建TomcatServletWebServerFactory注入进Spring容器
   @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;
   }

}

应用启动执行至上下文刷新

//org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
       ...
       // Initialize other special beans in specific context subclasses.
       //用于子类扩展
       onRefresh();
       ...
   }
}

onRefresh

//org.springframework.context.support.AbstractApplicationContext#onRefresh
protected void onRefresh() throws BeansException {
   // For subclasses: do nothing by default.
}

//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
protected void onRefresh() {
   super.onRefresh();
   try {
      //创建并启动web服务器
      createWebServer();
   }
   catch (Throwable ex) {
      throw new ApplicationContextException("Unable to start web server", ex);
   }
}

createWebServer

//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer
private void createWebServer() {
   //webServer、servletContext均为null
   WebServer webServer = this.webServer;
   ServletContext servletContext = getServletContext();
   if (webServer == null && servletContext == null) {
      StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
      //获取web服务器工厂
      ServletWebServerFactory factory = getWebServerFactory();
      createWebServer.tag("factory", factory.getClass().toString());
      //获取web服务器
      this.webServer = factory.getWebServer(getSelfInitializer());
      createWebServer.end();
      //向Spring容器注册webServerGracefulShutdown Bean对象
      //阻止处理新请求,并在尝试结束时调用给定的callback方法
      getBeanFactory().registerSingleton("webServerGracefulShutdown",
            new WebServerGracefulShutdownLifecycle(this.webServer));
      //向Spring容器注册webServerStartStop Bean对象
      //启动关闭server
      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);
      }
   }
   //初始化servletContextInitParams,servletConfigInitParams web服务器属性资源
   initPropertySources();
}

getWebServerFactory

//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#getWebServerFactory
protected ServletWebServerFactory getWebServerFactory() {
   // Use bean names so that we don't consider the hierarchy
   String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
   //ServletWebServerFactory为空抛出异常
   if (beanNames.length == 0) {
      throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
            + "ServletWebServerFactory bean.");
   }
   //ServletWebServerFactory实例个数大于1抛出异常
   if (beanNames.length > 1) {
      throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
            + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
   }
   //只能构建一个ServletWebServerFactory
   return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}

getWebServer

//org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
public WebServer getWebServer(ServletContextInitializer... initializers) {
   if (this.disableMBeanRegistry) {
      Registry.disableRegistry();
   }
   //构建tomcat对象
   Tomcat tomcat = new Tomcat();
   //设置根路径
   //C:\Users\Huang\AppData\Local\Temp\tomcat.端口.5924126900833427784
   File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   //设置生命周期监听器
   for (LifecycleListener listener : this.serverLifecycleListeners) {
      tomcat.getServer().addLifecycleListener(listener);
   }
   //构建连接器 赋值默认通讯协议org.apache.coyote.http11.Http11NioProtocol
   Connector connector = new Connector(this.protocol);
   //异常重新抛出
   connector.setThrowOnFailure(true);
   //添加连接器
   tomcat.getService().addConnector(connector);
   //根据扩展配置定制connector
   customizeConnector(connector);
   //设置连接器
   tomcat.setConnector(connector);
   //非自动部署
   tomcat.getHost().setAutoDeploy(false);
   //配置engine StandardEngine[Tomcat]
   configureEngine(tomcat.getEngine());
   //添加额外的tomcat连接器
   for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
   }
   //准备上下文
   prepareContext(tomcat.getHost(), initializers);
   //获取tomcat web服务器
   return getTomcatWebServer(tomcat);
}

customizeConnector

//org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#customizeConnector
protected void customizeConnector(Connector connector) {
   //获取并设置端口号 默认8080
   int port = Math.max(getPort(), 0);
   connector.setPort(port);
   if (StringUtils.hasText(getServerHeader())) {
      connector.setProperty("server", getServerHeader());
   }
   //设置协议address
   if (connector.getProtocolHandler() instanceof AbstractProtocol) {
      customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
   }
   //执行protocolHandler自定义扩展
   invokeProtocolHandlerCustomizers(connector.getProtocolHandler());
   //编码设置 默认StandardCharsets.UTF_8
   if (getUriEncoding() != null) {
      connector.setURIEncoding(getUriEncoding().name());
   }
   //如果ApplicationContext启动缓慢,不要过早地绑定到套接字
   connector.setProperty("bindOnInit", "false");
   //http2协议设置
   if (getHttp2() != null && getHttp2().isEnabled()) {
      connector.addUpgradeProtocol(new Http2Protocol());
   }
   //ssl设置
   if (getSsl() != null && getSsl().isEnabled()) {
      customizeSsl(connector);
   }
   //执行压缩连接器自定义扩展
   TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
   compression.customize(connector);
   //执行TomcatConnectorCustomizer自定义扩展
   for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
      customizer.customize(connector);
   }
}

getTomcatWebServer

//org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getTomcatWebServer
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
   return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
}

TomcatWebServer

//org.springframework.boot.web.embedded.tomcat.TomcatWebServer#TomcatWebServer(org.apache.catalina.startup.Tomcat, boolean, org.springframework.boot.web.server.Shutdown)
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;
   //初始化
   initialize();
}

initialize

//org.springframework.boot.web.embedded.tomcat.TomcatWebServer#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
         this.tomcat.start();
         // 可以直接在主线程中重新抛出失败异常
         rethrowDeferredStartupExceptions();
         try {
            ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
         }
         catch (NamingException ex) {
            // Naming is not enabled. Continue
         }
         //与Jetty不同,所有Tomcat线程都是守护线程, 我们创建一个阻塞的非守护进程来阻止立即关机
         startDaemonAwaitThread();
      }
      catch (Exception ex) {
         stopSilently();
         destroySilently();
         throw new WebServerException("Unable to start embedded Tomcat", ex);
      }
   }
}

startDaemonAwaitThread

//org.springframework.boot.web.embedded.tomcat.TomcatWebServer#startDaemonAwaitThread
private void startDaemonAwaitThread() {
   Thread awaitThread = new Thread("container-" + (containerCounter.get())) {
      @Override
      public void run() {
         TomcatWebServer.this.tomcat.getServer().await();
      }
   };
   awaitThread.setContextClassLoader(getClass().getClassLoader());
   //设置为用户线程
   awaitThread.setDaemon(false);
   awaitThread.start();
}

扩展jetty容器配置

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
    <version>2.6.6version>
    
    <exclusions>
        <exclusion>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-tomcatartifactId>
        exclusion>
    exclusions>
dependency>


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-jettyartifactId>
    <version>2.6.6version>
dependency>

感谢阅读完本篇文章!!!
个人博客地址: huanghong.top

你可能感兴趣的:(Springboot,tomcat,spring,boot,java)