日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

厉害了!SpringBoot是如何动起来的!

發(fā)布時(shí)間:2025/3/21 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 厉害了!SpringBoot是如何动起来的! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作者:襄垣

juejin.im/post/5c6f730ce51d457f14363a53

程序入口

SpringApplication.run(BeautyApplication.class,?args);

執(zhí)行此方法來(lái)加載整個(gè)SpringBoot的環(huán)境。

1. 從哪兒開始?

SpringApplication.java

????/***?Run?the?Spring?application,?creating?and?refreshing?a?new*?{@link?ApplicationContext}.*?@param?args?the?application?arguments?(usually?passed?from?a?Java?main?method)*?@return?a?running?{@link?ApplicationContext}*/public?ConfigurableApplicationContext?run(String...?args)?{//...}

調(diào)用SpringApplication.java 中的 run 方法,目的是加載Spring Application,同時(shí)返回 ApplicationContext。

2. 執(zhí)行了什么?

2.1 計(jì)時(shí)

記錄整個(gè)Spring Application的加載時(shí)間!

StopWatch?stopWatch?=?new?StopWatch(); stopWatch.start(); //?... stopWatch.stop(); if?(this.logStartupInfo)?{new?StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),?stopWatch); }

2.2 聲明

//?聲明?ApplicationContext ConfigurableApplicationContext?context?=?null; //?聲明?一個(gè)異常報(bào)告集合 Collection<SpringBootExceptionReporter>?exceptionReporters?=?new?ArrayList<>();

2.3 指定程序運(yùn)行模式

指定 java.awt.headless,默認(rèn)是true 一般是在程序開始激活headless模式,告訴程序,現(xiàn)在你要工作在Headless mode下,就不要指望硬件幫忙了,你得自力更生,依靠系統(tǒng)的計(jì)算能力模擬出這些特性來(lái)。

private?void?configureHeadlessProperty()?{System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,?System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,?Boolean.toString(this.headless))); }

2.4 配置監(jiān)聽并發(fā)布應(yīng)用啟動(dòng)事件

SpringApplicationRunListener 負(fù)責(zé)加載 ApplicationListener事件。

SpringApplicationRunListeners?listeners?=?getRunListeners(args); //?開始 listeners.starting(); //?處理所有?property?sources?配置和?profiles?配置,準(zhǔn)備環(huán)境,分為標(biāo)準(zhǔn)?Servlet?環(huán)境和標(biāo)準(zhǔn)環(huán)境 ConfigurableEnvironment?environment?=?prepareEnvironment(listeners,applicationArguments); //?準(zhǔn)備應(yīng)用上下文 prepareContext(context,?environment,?listeners,?applicationArguments,printedBanner); //?完成 listeners.started(context); //?異常 handleRunFailure(context,?ex,?exceptionReporters,?listeners); //?執(zhí)行 listeners.running(context);

getRunListeners 中根據(jù) type = SpringApplicationRunListener.class 去拿到了所有的 Listener 并根據(jù)優(yōu)先級(jí)排序。

對(duì)應(yīng)的就是 META-INF/spring.factories 文件中的 org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener

private?<T>?Collection<T>?getSpringFactoriesInstances(Class<T>?type,Class<?>[]?parameterTypes,?Object...?args)?{ClassLoader?classLoader?=?Thread.currentThread().getContextClassLoader();//?Use?names?and?ensure?unique?to?protect?against?duplicatesSet<String>?names?=?new?LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type,?classLoader));List<T>?instances?=?createSpringFactoriesInstances(type,?parameterTypes,classLoader,?args,?names);AnnotationAwareOrderComparator.sort(instances);return?instances;}

在 ApplicationListener 中 , 可以針對(duì)任何一個(gè)階段插入處理代碼。

public?interface?SpringApplicationRunListener?{/***?Called?immediately?when?the?run?method?has?first?started.?Can?be?used?for?very*?early?initialization.*/void?starting();/***?Called?once?the?environment?has?been?prepared,?but?before?the*?{@link?ApplicationContext}?has?been?created.*?@param?environment?the?environment*/void?environmentPrepared(ConfigurableEnvironment?environment);/***?Called?once?the?{@link?ApplicationContext}?has?been?created?and?prepared,?but*?before?sources?have?been?loaded.*?@param?context?the?application?context*/void?contextPrepared(ConfigurableApplicationContext?context);/***?Called?once?the?application?context?has?been?loaded?but?before?it?has?been*?refreshed.*?@param?context?the?application?context*/void?contextLoaded(ConfigurableApplicationContext?context);/***?The?context?has?been?refreshed?and?the?application?has?started?but*?{@link?CommandLineRunner?CommandLineRunners}?and?{@link?ApplicationRunner*?ApplicationRunners}?have?not?been?called.*?@param?context?the?application?context.*?@since?2.0.0*/void?started(ConfigurableApplicationContext?context);/***?Called?immediately?before?the?run?method?finishes,?when?the?application?context?has*?been?refreshed?and?all?{@link?CommandLineRunner?CommandLineRunners}?and*?{@link?ApplicationRunner?ApplicationRunners}?have?been?called.*?@param?context?the?application?context.*?@since?2.0.0*/void?running(ConfigurableApplicationContext?context);/***?Called?when?a?failure?occurs?when?running?the?application.*?@param?context?the?application?context?or?{@code?null}?if?a?failure?occurred?before*?the?context?was?created*?@param?exception?the?failure*?@since?2.0.0*/void?failed(ConfigurableApplicationContext?context,?Throwable?exception);}

3. 每個(gè)階段執(zhí)行的內(nèi)容

3.1 listeners.starting();

在加載Spring Application之前執(zhí)行,所有資源和環(huán)境未被加載。

3.2 prepareEnvironment(listeners, applicationArguments);

創(chuàng)建 ConfigurableEnvironment;將配置的環(huán)境綁定到Spring Application中;

????private?ConfigurableEnvironment?prepareEnvironment(SpringApplicationRunListeners?listeners,ApplicationArguments?applicationArguments)?{//?Create?and?configure?the?environmentConfigurableEnvironment?environment?=?getOrCreateEnvironment();configureEnvironment(environment,?applicationArguments.getSourceArgs());listeners.environmentPrepared(environment);bindToSpringApplication(environment);if?(this.webApplicationType?==?WebApplicationType.NONE)?{environment?=?new?EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}ConfigurationPropertySources.attach(environment);return?environment;}

3.3 prepareContext

配置忽略的Bean;

????private?void?configureIgnoreBeanInfo(ConfigurableEnvironment?environment)?{if?(System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME)?==?null)?{Boolean?ignore?=?environment.getProperty("spring.beaninfo.ignore",Boolean.class,?Boolean.TRUE);System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,ignore.toString());}}

打印日志-加載的資源

Banner?printedBanner?=?printBanner(environment);

根據(jù)不同的WebApplicationType創(chuàng)建Context

context?=?createApplicationContext();

3.4 refreshContext

支持定制刷新

????/***?Register?a?shutdown?hook?with?the?JVM?runtime,?closing?this?context*?on?JVM?shutdown?unless?it?has?already?been?closed?at?that?time.*?<p>This?method?can?be?called?multiple?times.?Only?one?shutdown?hook*?(at?max)?will?be?registered?for?each?context?instance.*?@see?java.lang.Runtime#addShutdownHook*?@see?#close()*/void?registerShutdownHook();

3.5 afterRefresh

刷新后的實(shí)現(xiàn)方法暫未實(shí)現(xiàn)

????/***?Called?after?the?context?has?been?refreshed.*?@param?context?the?application?context*?@param?args?the?application?arguments*/protected?void?afterRefresh(ConfigurableApplicationContext?context,ApplicationArguments?args)?{}

3.6 listeners.started(context);

到此為止, Spring Application的環(huán)境和資源都加載完畢了;發(fā)布應(yīng)用上下文啟動(dòng)完成事件;執(zhí)行所有 Runner 運(yùn)行器 - 執(zhí)行所有 ApplicationRunner 和 CommandLineRunner 這兩種運(yùn)行器。

//?啟動(dòng) callRunners(context,?applicationArguments);

3.7 listeners.running(context);

觸發(fā)所有 SpringApplicationRunListener 監(jiān)聽器的 running 事件方法

總結(jié)

以上是生活随笔為你收集整理的厉害了!SpringBoot是如何动起来的!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。