【Spring boot】整合tomcat底层原理( 二 )

  • 对于另外的EmbeddedJetty和EmbeddedUndertow,逻辑类似 , 都是判断项目依赖中是否有Jetty和Undertow的依赖,如果有,那么对应在Spring容器中就会存在JettyServletWebServerFactory类型的Bean、或者存在UndertowServletWebServerFactory类型的Bean 。
TomcatServletWebServerFactory的作用:获取WebServer对象
  • TomcatServletWebServerFactory他实现了ServletWebServerFactory这个接口 。
  • ServletWebServerFactory接口内部只有一个方法是获取WebServer对象 。

【Spring boot】整合tomcat底层原理

文章插图
  • WebServer拥有启动、停止、获取端口等方法,就会发现WebServer其实指的就是Tomcat、Jetty、Undertow 。

【Spring boot】整合tomcat底层原理

文章插图
  • 而TomcatServletWebServerFactory就是用来生成Tomcat所对应的WebServer对象 , 具体一点就是TomcatWebServer对象,并且在生成TomcatWebServer对象时会把Tomcat给启动起来 。
  • 在源码中,调用TomcatServletWebServerFactory对象的getWebServer()方法时就会启动Tomcat 。
public WebServer getWebServer(ServletContextInitializer... initializers) {    if (this.disableMBeanRegistry) {        Registry.disableRegistry();    }    // 构建tomcat对象    Tomcat tomcat = new Tomcat();    // 设置相关的属性    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");    tomcat.setBaseDir(baseDir.getAbsolutePath());    for (LifecycleListener listener : this.serverLifecycleListeners) {        tomcat.getServer().addLifecycleListener(listener);    }    Connector connector = new Connector(this.protocol);    connector.setThrowOnFailure(true);    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,这个方法内部有this.tomcat.start();    return getTomcatWebServer(tomcat);}spring boot启动的时候启动tomcat
  • SpringBoot的启动过程中,会调用核心的refresh方法,内部会执行onRefresh()方法,onRefresh()方法是一个模板方法,他会执行会执行子类ServletWebServerApplicationContext的onRefresh()方法 。
【【Spring boot】整合tomcat底层原理】protected void onRefresh() {    // 模板方法 , 先调用它父类的,一般是空方法    super.onRefresh();    try {        // 创建web容器        createWebServer();    }    catch (Throwable ex) {        throw new ApplicationContextException("Unable to start web server", ex);    }}
  • 这个方法会调用createWebServer()方法 。
// 最核心的俩行代码private void createWebServer() {    ......    // 获取web容器,多个或者没有的时候报错    ServletWebServerFactory factory = getWebServerFactory();    // 调用这个容器的getWebServer方法,上面的启动tomcat的方法!    this.webServer = factory.getWebServer(getSelfInitializer());    ......}
  • getWebServerFactory控制项目组有且只能有一个web容器!
protected ServletWebServerFactory getWebServerFactory() {    // Use bean names so that we don't consider the hierarchy    // 得到所有类型为ServletWebServerFactory的Bean 。TomcatServletWebServerFactory、JettyServletWebServerFactory、UndertowServletWebServerFactory都是他得到子类!    String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);    // 不存在,报错    if (beanNames.length == 0) {        throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");    }    // 存在不止一个,报错!    if (beanNames.length > 1) {        throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));    }    // 返回唯一的一个web容器!    return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);}

推荐阅读