springboot啟動(dòng)(2) -- 啟動(dòng)流程

根據(jù)springboot啟動(dòng)(1)的分析昆雀,springboot真正啟動(dòng)從應(yīng)用主類(lèi)main方法開(kāi)始湿酸,其run方法中由SpringApplication完成真正啟動(dòng)陷虎。

  1. new SpringApplication
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = Collections.emptySet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrappers = new ArrayList(this.getSpringFactoriesInstances(Bootstrapper.class));
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
  • 配置是否為web應(yīng)用的lambda方法(默認(rèn)web應(yīng)用)
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
  • 創(chuàng)建應(yīng)用上下文工廠递胧,用于自動(dòng)裝配等(默認(rèn)SERVLET囚痴,及支持注解的servlet)
@FunctionalInterface
public interface ApplicationContextFactory {
    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
        try {
            switch(webApplicationType) {
            case SERVLET:
                return new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
            }
        } catch (Exception var2) {
            throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var2);
        }
    };
  • 讀取spring.factories文件獲取監(jiān)聽(tīng)配置并創(chuàng)建監(jiān)聽(tīng)器
  • 配置應(yīng)用啟動(dòng)類(lèi)
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
  1. SpringApplication.run
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
  • 監(jiān)聽(tīng)器發(fā)布應(yīng)用開(kāi)始啟動(dòng)
  • 獲取應(yīng)用配置:ConfigurableEnvironment(包含logger募寨、應(yīng)用環(huán)境族展、應(yīng)用參數(shù)等)
  • 創(chuàng)建應(yīng)用上下文:createApplicationContext
    默認(rèn)AnnotationConfigServletWebServerApplicationContext,讀取配置環(huán)境拔鹰、加載監(jiān)聽(tīng)仪缸,構(gòu)造資源加載器reader、pacakge scanner列肢,構(gòu)造bean工廠加載器恰画。
  • 啟動(dòng)前準(zhǔn)備工作:prepareContext
    通過(guò)bean工廠生產(chǎn)所需bean,配置各類(lèi)資源
  • 刷新上下文:refreshContext
    自動(dòng)裝配springboot配置組件(如mybatis等)瓷马,創(chuàng)建web server(如tomcat)拴还。
  • 再刷新上下文(空實(shí)現(xiàn)留作擴(kuò)展)
  • 發(fā)布啟動(dòng)完成事件
  1. 自動(dòng)裝配
    自動(dòng)裝配在AbstractApplicationContext.refresh中完成的,由invokeBeanFactoryPostProcessors方法執(zhí)行自動(dòng)裝配鏈條欧聘。
  • 獲取bean工廠加載器片林、資源加載器
  • 資源加載器讀取spring.factories配置文件,獲取待加載bean及其全路徑
  • 通過(guò)反射獲取待加載bean的class對(duì)象和構(gòu)造方法
  • 實(shí)例化所有待加載bean怀骤,并加入spring容器

上述3個(gè)步驟就是springboot啟動(dòng)大致流程费封,前期主要完成配置環(huán)境讀取、加載監(jiān)聽(tīng)器蒋伦、構(gòu)造工廠加載器合和資源加載器弓摘。其中核心是在刷新上下文refreshContext,包含了web server的啟動(dòng)和自動(dòng)裝備凉敲。

自動(dòng)裝配流程:

  • @EnableAutoConfiguration模塊的
    通過(guò)自定義@Enable模塊驅(qū)動(dòng)測(cè)試知道衣盾,springboot通過(guò)@ImportSelector等注解類(lèi),實(shí)現(xiàn)bean的實(shí)例化和注入爷抓。@EnableAutoConfiguration同樣的實(shí)現(xiàn)原理势决,其ImportSelector接口方法實(shí)現(xiàn)中會(huì)掃描項(xiàng)目下的spring.factories,獲取待加載類(lèi)蓝撇。
  • 讀取各jar包下spring.factories文件的配置內(nèi)容果复,該文件結(jié)構(gòu)為:接口=接口實(shí)現(xiàn)類(lèi)列表,比如mongodb的jar包下
org.springframework.data.web.config.SpringDataJacksonModules=org.springframework.data.mongodb.config.GeoJsonConfiguration
org.springframework.data.repository.core.support.RepositoryFactorySupport=org.springframework.data.mongodb.repository.support.MongoRepositoryFactory
  • @EnableAutoConfiguration模塊獲取到類(lèi)后渤昌,通過(guò)工廠反射實(shí)例化待加載類(lèi)虽抄。

在springboot的各功能模塊spring.factories文件中配置了大量默認(rèn)實(shí)現(xiàn)接口走搁。再加上springboot的條件裝配,通過(guò)配置文件實(shí)現(xiàn)配置的功能模塊迈窟。比如私植,springboot中包含了mongodb的實(shí)現(xiàn)MongoTemplate,只需要在配置文件中添加mongodb的依賴(lài)车酣,就能在自動(dòng)裝配接的完成mongodb服務(wù)MongoTemplate的加載曲稼。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

springboot這種帶有默認(rèn)實(shí)現(xiàn)的配置方式,體現(xiàn)了其“規(guī)約大于配置”的思想湖员,用戶開(kāi)箱即用贫悄,極大提高了開(kāi)發(fā)效率。

參考:https://www.cnblogs.com/trgl/p/7353782.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娘摔,一起剝皮案震驚了整個(gè)濱河市窄坦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凳寺,老刑警劉巖鸭津,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異肠缨,居然都是意外死亡曙博,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)怜瞒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人般哼,你說(shuō)我怎么就攤上這事吴汪。” “怎么了蒸眠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵漾橙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我楞卡,道長(zhǎng)霜运,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任蒋腮,我火速辦了婚禮淘捡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘池摧。我一直安慰自己焦除,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布作彤。 她就那樣靜靜地躺著膘魄,像睡著了一般乌逐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上创葡,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天浙踢,我揣著相機(jī)與錄音,去河邊找鬼灿渴。 笑死洛波,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的逻杖。 我是一名探鬼主播奋岁,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荸百!你這毒婦竟也來(lái)了闻伶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤够话,失蹤者是張志新(化名)和其女友劉穎蓝翰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體女嘲,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畜份,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欣尼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆雹。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愕鼓,靈堂內(nèi)的尸體忽然破棺而出钙态,到底是詐尸還是另有隱情,我是刑警寧澤菇晃,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布册倒,位于F島的核電站,受9級(jí)特大地震影響磺送,放射性物質(zhì)發(fā)生泄漏驻子。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一估灿、第九天 我趴在偏房一處隱蔽的房頂上張望崇呵。 院中可真熱鬧,春花似錦甲捏、人聲如沸演熟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)芒粹。三九已至兄纺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間化漆,已是汗流浹背估脆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留座云,地道東北人疙赠。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像朦拖,于是被迫代替她去往敵國(guó)和親圃阳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

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