spring-boot Tomcat初始化源碼分析

基本實(shí)現(xiàn)說(shuō)明

spring-boot-starter-tomcat默認(rèn)會(huì)被spring-boot-starter所依賴(lài)褐啡,而spring-boot實(shí)現(xiàn)的巧妙方式在于,通過(guò)依賴(lài)判定當(dāng)前classpath下是否存在Tomcat類(lèi)來(lái)斷定锣杂,當(dāng)前web容器類(lèi)型也颤。
這種方式也是spring-boot實(shí)現(xiàn)通過(guò)配置來(lái)決定啟用何種服務(wù)的根本原理。

代碼分析

spring-boot容器的默認(rèn)超類(lèi)是EmbeddedWebApplicationContext炭玫,而真正初始化容器的過(guò)程是調(diào)用createEmbeddedServletContainer方法卵凑。
EmbeddedWebApplicationContext

    private void createEmbeddedServletContainer() {
        EmbeddedServletContainer localContainer = this.embeddedServletContainer;
        ServletContext localServletContext = getServletContext();
        if (localContainer == null && localServletContext == null) {
            EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
            // 從容器中查找實(shí)例,方法如下
            this.embeddedServletContainer = containerFactory
                    .getEmbeddedServletContainer(getSelfInitializer());
        }
        else if (localServletContext != null) {
            try {
                getSelfInitializer().onStartup(localServletContext);
            }
            catch (ServletException ex) {
                throw new ApplicationContextException("Cannot initialize servlet context",
                        ex);
            }
        }
        initPropertySources();
    }
    protected EmbeddedServletContainerFactory getEmbeddedServletContainerFactory() {
        // Use bean names so that we don't consider the hierarchy
        String[] beanNames = getBeanFactory()
                .getBeanNamesForType(EmbeddedServletContainerFactory.class);
        ....
        ....
    }

即查找類(lèi)型為EmbeddedServletContainerFactory.class的對(duì)象庆聘,而此對(duì)象的BeanDefinition放入的時(shí)機(jī)則是通過(guò)配置來(lái)實(shí)現(xiàn)的。

其中有一個(gè)過(guò)程是通過(guò)EnableAutoConfigurationImportSelector查找在在spring.factories中配置的所有類(lèi)型為org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置類(lèi)勺卢,而這些默認(rèn)實(shí)現(xiàn)類(lèi)在spring-boot-starter.autoconfigure中伙判,截取部分如下

...
...
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
...
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
\
....
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
...

查看其中的org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {

    @Configuration
    @ConditionalOnClass({ Servlet.class, Tomcat.class })
    @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    public static class EmbeddedTomcat {

        @Bean
        public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
            return new TomcatEmbeddedServletContainerFactory();
        }

    }

    @Configuration
    @ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
            WebAppContext.class })
    @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    public static class EmbeddedJetty {

        @Bean
        public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
            return new JettyEmbeddedServletContainerFactory();
        }
    }
    ...
    ...

}

這個(gè)提供了默認(rèn)三種web容器,Tomcat,Jetty,Undertow黑忱,而@ConditionalOnClass注解的配置決定了在什么情況下使用這個(gè)類(lèi)宴抚,類(lèi)似Profile的功能。此條件判斷依據(jù)為當(dāng)前classpath容器中存在是否存在配置的class甫煞,以EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat來(lái)說(shuō)菇曲,它存在的依據(jù)在于當(dāng)前classpath存在Servlet類(lèi)和Tomcat類(lèi),而spring-boot默認(rèn)依賴(lài)Tomcat抚吠,所以EmbeddedTomcat將被激活常潮,而EmbeddedServletContainerAutoConfiguration$EmbeddedJetty將不會(huì)被采用。
所以楷力,如果你想要使用jetty容器喊式,僅僅需要將Tomcat依賴(lài)排除,并添加Jetty依賴(lài)即可萧朝,其他容器同理岔留。
此時(shí)容器中已經(jīng)確定了web容器,初始化的代碼就在TomcatEmbeddedServletContainerFactory#getEmbeddedServletContainer

public EmbeddedServletContainer getEmbeddedServletContainer(
            ServletContextInitializer... initializers) {
        Tomcat tomcat = new Tomcat();
        File baseDir = (this.baseDirectory != null ? this.baseDirectory
                : createTempDir("tomcat"));
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        Connector connector = new Connector(this.protocol);
        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);
        return getTomcatEmbeddedServletContainer(tomcat);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末检柬,一起剝皮案震驚了整個(gè)濱河市献联,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌何址,老刑警劉巖里逆,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異头朱,居然都是意外死亡运悲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)项钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)班眯,“玉大人希停,你說(shuō)我怎么就攤上這事∈鸢” “怎么了宠能?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)磁餐。 經(jīng)常有香客問(wèn)我违崇,道長(zhǎng),這世上最難降的妖魔是什么诊霹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任羞延,我火速辦了婚禮,結(jié)果婚禮上脾还,老公的妹妹穿的比我還像新娘伴箩。我一直安慰自己,他們只是感情好鄙漏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布嗤谚。 她就那樣靜靜地躺著,像睡著了一般怔蚌。 火紅的嫁衣襯著肌膚如雪巩步。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天桦踊,我揣著相機(jī)與錄音椅野,去河邊找鬼。 笑死钞钙,一個(gè)胖子當(dāng)著我的面吹牛鳄橘,可吹牛的內(nèi)容都是我干的声离。 我是一名探鬼主播芒炼,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼术徊!你這毒婦竟也來(lái)了本刽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赠涮,失蹤者是張志新(化名)和其女友劉穎子寓,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體笋除,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斜友,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垃它。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲜屏。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烹看,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出洛史,到底是詐尸還是另有隱情惯殊,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布也殖,位于F島的核電站土思,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忆嗜。R本人自食惡果不足惜己儒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捆毫。 院中可真熱鬧址愿,春花似錦、人聲如沸冻璃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)省艳。三九已至娘纷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跋炕,已是汗流浹背赖晶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辐烂,地道東北人遏插。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像纠修,于是被迫代替她去往敵國(guó)和親胳嘲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容