SpringBoot 2.x 版本 嵌入式Servlet容器自動配置原理以及啓動原理(超詳細)

一、版本說明:

Spring Boot 2.x 版本的嵌入式Servlet容器自動配置是通過 WebServerFactoryCustomizer定製器 來定製的,而在Spring Boot 1.x 版本中我們是通過 EmbeddedServletContainerCustomizer 嵌入式的Servlet容器定製器來定製的。由於之前看的資料都是1.x的版本,但是我使用的是2.x,所以在這裏記錄一下2.x版本的嵌入式Servlet容器自動配置原理以及啓動原理。

二、總結

嵌入式Servlet容器自動配置原理以及啓動原理有三大步:

步驟:

  1. SpringBoot 根據導入的依賴信息,自動創建對應的 WebServerFactoryCustomizer(web服務工廠定製器);
  2.  WebServerFactoryCustomizerBeanPostProcessor(web服務工廠定製器組件的後置處理器)獲取所有類型爲web服務工廠定製器的組件(包含實現WebServerFactoryCustomizer接口,自定義的定製器組件),依次調用customize()定製接口,定製Servlet容器配置;
  3. 嵌入式的Servlet容器工廠創建tomcat容器,初始化並啓動容器。

三、嵌入式Servlet容器自動配置原理(以Tomcat爲例)

1、首先找到 EmbeddedWebServerFactoryCustomizerAutoConfiguration ,在裏面我們可以看到SpringBoot支持的              servlet容器

//SprinBoot支持的servlet容器有三個Tomcat、Jetty、Undertow,但是默認配置的是Tomcat


//嵌入式的Undertow
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Undertow.class, SslClientAuthMode.class})
    public static class UndertowWebServerFactoryCustomizerConfiguration {
        public UndertowWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
        }
    }


//嵌入式的Jetty
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Server.class, Loader.class, WebAppContext.class})
    public static class JettyWebServerFactoryCustomizerConfiguration {
        public JettyWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new JettyWebServerFactoryCustomizer(environment, serverProperties);
        }
    }

//嵌入式的Tomcat
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Tomcat.class, UpgradeProtocol.class})
    public static class TomcatWebServerFactoryCustomizerConfiguration {
        public TomcatWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
        }
    }

2、準備環節

1)在以下位置打一個斷點

2)、點進 TomcatWebServerFactoryCustomizer 也就是上圖 return 的,然後在裏面的如下位置打一個斷點

3)、然後在裏面debug程序,我們在控制檯就可以看到如下信息

3、按照上圖從下往上分析。我們啓動springboot應用時,都是直接運行主程序的main方法,然後調用裏面的run方法,如下圖

4、調用完run方法,回來到 refreshContext 方法,這個方法是幫我們創建IOC容器對象,並且初始化容器創建容器中的每一個組件

5、在調用了 reflesh 方法刷新剛纔的IOC容器後,來到 onreflesh 方法,調用createWebServer()方法,創建WebServer

6、來到createWebServer()方法,該方法最終能夠獲取到一個與當前應用(也就是總結裏說的第一步,根據我們導入的依賴來獲取)所導入的Servlet類型相匹配的web服務工廠,通過工廠就可以獲取到相應的  WebServerFactoryCustomizer (Web服務工廠定製器)

注:createWebServer()執行後,我們其實來到了 EmbeddedWebServerFactoryCustomizerAutoConfiguration,然後根據條件(配置的依賴)配置哪一個Web服務器

我們通過查看 ServletWebServerFactory 的子類,可以看到其中三個就是Tomcat、Jetty和Undertow,根據我們的配置,所以這裏獲取到的是 TomcatWebServerFactoryCustomizer

至此,TomcatWebServerFactoryCustomizer組件創建完成,對應的服務配置類也已添加到IOC容器。

7、因爲容器中某個組件要創建對象就會驚動後置處理器 然後就到 WebServerFactoryCustomizerBeanPostProcessor(web服務工廠定製器組件的後置處理器),該類負責在bean組件初始化之前執行初始化工作。它先從IOC容器中獲取所有類型爲WebServerFactoryCustomizerBeans(web服務工廠定製器的組件)

通過後置處理器獲取到的TomcatWebServerFactoryCustomizer調用customize()定製方法,獲取到Servlet容器相關配置類ServerProperties,進行自動配置

至此,嵌入式Servlet容器的自動配置完成。

注:從源碼分析可以得出配置嵌入式Servlet容器的兩種解決方案: 

1、在全局配置文件中,通過server.xxx來修改和server有關的配置:

server.port=8081
server.tomcat.xxx...

2、實現WebServerFactoryCustomizer接口,重寫它的customize()方法,對容器進行定製配置:

@FunctionalInterface
public interface WebServerFactoryCustomizer<T extends WebServerFactory> {
    void customize(T factory);
}

 四、嵌入式Servlet容器啓動原理(以Tomcat爲例)

1、應用啓動後,根據導入的依賴信息,創建了相應的Servlet容器工廠,創建了TomcatServletWebServerFactory,調用getWebServer()方法創建Tomcat容器:(其實就是重寫了ServletWebServerFactory裏面的getWebServer方法

找到下面的getTomcatWebServer方法

2、然後點進去分析TomcatWebServer的有參構造器,執行 initialize() 方法

3、點進去就可以發現,裏面通過調用start方法來啓動Tomcat

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章