【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);}

推薦閱讀