欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot超詳細(xì)分析啟動流程

 更新時間:2022年07月13日 10:16:13   作者:麥神-mirson  
SpringBoot是Spring開源組織下的子項目,是Spring組件一站式解決方案,主要是簡化了使用Spring的難度,簡省了繁重的配置,提供了各種啟動器,開發(fā)者能快速上手,這篇文章主要給大家介紹了關(guān)于Spring Boot啟動流程知識點的相關(guān)資料,需要的朋友可以參考下

一、Spring Boot 工程結(jié)構(gòu)

下載Spring Boot工程源碼, 下載地址

模塊代碼結(jié)構(gòu):

比較重要的是Spring-boot、Spring-boot-autoconfigure以及Spring-boot-starters等組件。

工程模塊介紹

spring-boot

spring boot框架核心插件,對其他模塊提供主要支持。內(nèi)部包含所熟知的SpringApplication類, 提供應(yīng)用程序入口, 內(nèi)嵌支持Tomcat、Jetty和Undertow等容器。

spring-boot-actuator

主要用于管理和監(jiān)控應(yīng)用, 支持http、jmx、ssh、telnet等連接管理方式。

包含審計、健康狀態(tài)、數(shù)據(jù)采集等功能。

spring-boot-actuator-autoconfigure

spring-boot-actuator的擴展、為其提供自動化配置功能。

spring-boot-autoconfigure

實現(xiàn)spring-boot工程的自動化配置, 我們常用的@EnableAutoConfiguration標(biāo)注,就是通過此工程實現(xiàn),

觸發(fā)Spring上下文的自動裝配。 設(shè)計目的是減少開發(fā)者的對bean及應(yīng)用組件的管理配置,專注自己的實現(xiàn)。

spring-boot-cli

提供Spring項目相關(guān)的命令行功能,

安裝CLI相關(guān)工具。即可通過spring run hello.groovy

直接運行Groovy腳本, 不過過多的繁瑣配置, 開發(fā)人員只需關(guān)注業(yè)務(wù)邏輯。

spring-boot-dependencies

Spring Boot項目的maven依賴管理工程, 定義管理各組件的版本號,

內(nèi)部沒有具體代碼實現(xiàn)。

spring-boot-devtools

Spring Boot的開發(fā)工具,比如經(jīng)常調(diào)試程序,使用該插件可以支持熱部署,

不需反復(fù)重啟, 提高開發(fā)效率。

spring-boot-docs

Spring Boot的文檔配置工程,設(shè)置文檔格式、樣式、布局等。

spring-boot-parent

Spring Boot的父級工程, 沒有代碼實現(xiàn), 主要通過dependencyManagement管理各子項目的maven組件依賴。

spring-boot-properties-migrator

Spring Boot的配置屬性監(jiān)察功能, 也就是通過監(jiān)聽器觀察指定的屬性KEY, 發(fā)生變化時,符合指定的匹配規(guī)則,將會觸發(fā)監(jiān)聽事件, 執(zhí)行日志或發(fā)送報告等。

spring-boot-starters

它是一個管理工程, 里面包含各種應(yīng)用組件,例如我們常用的spring-boot-starter-web組件, 提供對web服務(wù)支持;spring-boot-starter-data-jdbc組件, 提供的jdbc數(shù)據(jù)源的封裝使用。里面每個組件只存在一個pom文件, 引入第三方依賴, 這樣能簡化配置, 靈活管理, 保障服務(wù)工程的兼容性。

spring-boot-test

里面包含各種模塊及標(biāo)注, 幫助我們方便測試spring boot 應(yīng)用程序。

spring-boot-test-autoconfigure

服務(wù)于spring-boot-test工程,提供自動化配置,便于集成使用。

spring-boot-tools

spring boot工程的管理工具, 比如ant和maven構(gòu)建、文檔配置工具等。

二、Spring Boot 啟動流程

Spring Boot 的整體啟動流程:

三、Spring Boot 啟動流程源碼剖析

1、創(chuàng)建一個Spring Boot 工程

創(chuàng)建spring-boot-startup工程作為源碼研究。

POM依賴:

<!-- Spring Boot Web 依賴組件 -->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2、SpringBootApplication啟動入口

com.mirson.spring.boot.research.startup.ResearchApplication, 啟動類代碼:

@SpringBootApplication
@ComponentScan(basePackages = {"com.mirson"})
public class ResearchApplication {
    public static void main(String[] args) {
        SpringApplication.run(ResearchApplication.class, args);
    }
}

核心@SpringBootApplication注解

@Target(ElementType.TYPE)            // 注解的適用范圍,其中TYPE用于描述類、接口(包括包注解類型)或enum聲明
@Retention(RetentionPolicy.RUNTIME)  // 注解的生命周期,保留到class文件中(三個生命周期)
@Documented                          // 表明這個注解應(yīng)該被javadoc記錄
@Inherited                           // 子類可以繼承該注解
@SpringBootConfiguration             // 繼承了Configuration,表示當(dāng)前是注解類
@EnableAutoConfiguration             // 開啟springboot的注解功能,springboot的四大神器之一,其借助@import的幫助
@ComponentScan(excludeFilters = {    // 掃描路徑設(shè)置,excludeFilters為排除的過濾器,啟動時不加載
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

打開其內(nèi)部, 實質(zhì)上就是@Configuration注解, 它是負(fù)責(zé)處理JavaConfig配置, 類似之前Spring在XML中定義的各種配置, 通過@Configuration注解, 會自動加載各種基于JavaConfig實現(xiàn)的配置。比如@Bean定義, @Autowire自動裝配等。

EnableAutoConfiguration

Spring Boot 內(nèi)部封裝了很多組件, 比如異步任務(wù), 緩存, 數(shù)據(jù)源等, EnableAutoConfiguration相當(dāng)于是個總開關(guān), 負(fù)責(zé)管理所有組件的自動化配置,它會去掃描當(dāng)前路徑下所有JavaConfig配置,并且通過AutoConfigurationImportSelector, 加載默認(rèn)的自動化配置組件。

ComponentScan

ComponentScan功能其實是自動掃描并加載符合條件的組件, 比如@Service、@Repository、@Component等, 把它們加載到Spring Ioc容器中。Spring Boot 項目默認(rèn)會掃描加載啟動類所在路徑下的所有JavaConfig配置, 通過ComponetScan指定package, 可以自定義路徑掃描。

3、Spring Boot 初始化分析

從SpringApplication的run方法進入:

創(chuàng)建SpringApplication對象, 查看構(gòu)造方法:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
 // 設(shè)置資源加載器
 this.resourceLoader = resourceLoader;
 Assert.notNull(primarySources, "PrimarySources must not be null");
 // 設(shè)置主資源加載器, 優(yōu)先級更高
 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
 // 應(yīng)用類型推斷處理, 標(biāo)識應(yīng)用服務(wù)是REACTIVE模式或SERVLET類型
 this.webApplicationType = WebApplicationType.deduceFromClasspath();
 // 設(shè)置初始化加載器,默認(rèn)有6個, 作用是讀取spring.factories配置, 每個初始加載器實現(xiàn)ApplicationContextInitializer接口
 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
 // 設(shè)置監(jiān)聽器, 默認(rèn)有10個, 包含配置文件, 日志, Classpath等監(jiān)聽器
 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
 // 設(shè)置啟動類信息
 this.mainApplicationClass = deduceMainApplicationClass();
}

Initializers初始化加載器

listeners監(jiān)聽器

4、Spring Boot 啟動深入分析

查看SpringApplication的run方法:

public ConfigurableApplicationContext run(String... args) {
 // ① 創(chuàng)建計時器
 StopWatch stopWatch = new StopWatch();
 // 計時器開始統(tǒng)計
 stopWatch.start();
 // ② 定義配置型上下文, 除了具備ApplicationContex, 還擁有生命周期和流屬性
 ConfigurableApplicationContext context = null;
 // ③ 定義異常記錄報告
 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
 // ④ 識別是否Headless模式, 該模式下,系統(tǒng)沒有顯示設(shè)備、鍵盤或鼠標(biāo)
 configureHeadlessProperty();
 // ⑤ 獲取所有Spring Boot 內(nèi)置監(jiān)聽器
 SpringApplicationRunListeners listeners = getRunListeners(args);
 // 啟動所有監(jiān)聽器
 listeners.starting();
 try {
     // ⑥ 設(shè)置服務(wù)啟動時接收的參數(shù)
     ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
     // 設(shè)置環(huán)境變量信息, 為監(jiān)聽器和ConfigurationPropertySources初始環(huán)境變量
     ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
     // ⑦ 忽略環(huán)境變量中配置的BEAN信息
     configureIgnoreBeanInfo(environment);
     // ⑧ 控制臺打印Banner條, 可以自定義圖片背景等
     Banner printedBanner = printBanner(environment);
     // ⑨ 創(chuàng)建上下文, 根據(jù)不同模式進行創(chuàng)建(SERVLET、REACTIVE)
     context = createApplicationContext();
     // ⑩ 獲取Spring Factory加載時的異常報告
     exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                                                      new Class[] { ConfigurableApplicationContext.class }, context);
     // ?  Spring上下文加載預(yù)處理
     prepareContext(context, environment, listeners, applicationArguments, printedBanner);
     // ? Spring 上下文加載處理
     refreshContext(context);
     // ? Spring 上下文加載完畢的后置處理, 內(nèi)部暫為空實現(xiàn)
     afterRefresh(context, applicationArguments);
     // 停止時間計時器
     stopWatch.stop();
     if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
     }
     // ? 啟動監(jiān)聽器
     listeners.started(context);
     // ? Spring Boot 容器啟動完畢后, 調(diào)用ApplicationRunner的run方法, 處理自定義邏輯
     callRunners(context, applicationArguments);
 }
 catch (Throwable ex) {
     handleRunFailure(context, ex, exceptionReporters, listeners);
     throw new IllegalStateException(ex);
 }
 try {
     // 執(zhí)行監(jiān)聽器
     listeners.running(context);
 }
 catch (Throwable ex) {
     handleRunFailure(context, ex, exceptionReporters, null);
     throw new IllegalStateException(ex);
 }
 return context;
}

① 創(chuàng)建StopWatch,Spring 提供的計時器,統(tǒng)計Spring Boot應(yīng)用啟動時長信息。

② 定義Spring上下文, 并下面第九處執(zhí)行賦值。

③ 定義異常報告集合, 收集Spring Factory的初始化異常信息。

④ 配置headless信息, 該模式下,系統(tǒng)沒有顯示設(shè)備、鍵盤或鼠標(biāo)。

⑤ 獲取啟動監(jiān)聽器,為一個集合,可以包含多個監(jiān)聽, 實現(xiàn)SpringApplicationRunListener接口,

該接口定義了容器啟動的完整生命周期, 如啟動、運行、環(huán)境準(zhǔn)備、上下文準(zhǔn)備、加載等。EventPublishingRunListener就是一個具體實現(xiàn),

將SpringApplicationRunListener接口監(jiān)聽到的事件, 轉(zhuǎn)化為SpringApplicationEvent事件, 注冊并廣播到所有監(jiān)聽器下面。

⑥ 服務(wù)配置處理,創(chuàng)建applicationArguments, 為應(yīng)用的命令行參數(shù), 啟動程序時可以指定, 比如—debug等; prepareEnvrionment根據(jù)參數(shù)加載屬性配置, 包含自定義的屬性配置,像我們常見的application.yml都會加載進去, 默認(rèn)會加載7個類型的配置到envrionment中。

⑦ configureIgnoreBeanInfo作用是配置是否忽略beaninfo處理, 默認(rèn)是為true,會自動忽略不檢索加載工程中的beaninfo類信息。

⑧ printBanner打印Spring Boot啟動的Banner條, 通過bannerMode屬性控制是否打印,內(nèi)部有g(shù)etImageBanner和getTextBanner實現(xiàn), 可以支持圖像與文本。

⑨ 容器創(chuàng)建, 通過createApplicationContext方法創(chuàng)建Spring容器, 會根據(jù)應(yīng)用類型, 加載不同上下文處理類。Web Servlet類型會加載AnnotationConfigServletWebServerApplicationContext; Reactive類型會 加載AnnotationConfigReactiveWebServerApplicationContext。都是繼承ServletWebServerApplicationContext類, 實現(xiàn)ConfigurableWebApplicationContext接口。 在不指 定應(yīng)用類型的i情況下,默認(rèn)通過AnnotationConfigApplicationContext類處理上下文,該類是繼承GenericApplicationContext,實現(xiàn)ConfigurableApplicationContext接口。

⑩ 初始化exceptionReports集合, 通過SpringFactory加載,

內(nèi)置有19個異常分析器, 常見的BeanDefinition定義錯誤、NoUnique唯一性約束、PortInUse端口占用等異常都是通過這些分析器處理拋出。

?上下文加載預(yù)處理,prepareContext方法內(nèi)部實現(xiàn):

設(shè)置context的environment環(huán)境配置屬性,通過applyInitializer初始化ApplicationContextInitializer。通知監(jiān)聽器告訴上下文預(yù)處理工作完成。 接下來創(chuàng)建所熟知的beanFactory容器管理工廠, 加載BeanDefinition, 最后通知監(jiān)聽器,加載完成。

? 刷新啟動Spring容器, 調(diào)用refreshConext方法。深入內(nèi)部,可以看到核心處理流程:

@Override
public void refresh() throws BeansException, IllegalStateException {
    // 設(shè)置同步鎖, 防止啟動關(guān)閉造成的資源爭搶
    synchronized (this.startupShutdownMonitor) {
        // Spring 上下文預(yù)加載處理
        prepareRefresh();
        // 刷新并返回bean工廠信息
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 預(yù)加載bean工廠信息, 如設(shè)定classloader加載器, 接口依賴等。
        prepareBeanFactory(beanFactory);
        try {
            // bean工廠處理, 設(shè)置上下文的BeanPostProcessor和ignoreDependencyInterface等信息
            postProcessBeanFactory(beanFactory);
            // 調(diào)用所有在BeanFactory中已注冊的beanFactoryPostProcessor。beanFactoryPostProcessor 是BeanFactory的后置處理器, 對BeanDefinition對象修改,如我們在XML或標(biāo)注配置的bean定義信息
            invokeBeanFactoryPostProcessors(beanFactory);
            // 通過委派機制注冊Bean創(chuàng)建時的Bean Processors對象 。BeanPostProcessor是Bean后置處理器, 負(fù)責(zé)對Bean對象修改, 比如實現(xiàn)InitializingBean接口的Bean, 通過afterPropertiesSet方法設(shè)置修改
            registerBeanPostProcessors(beanFactory);
            // 初始化message source , 比如我們常見的國際化信息處理。
            initMessageSource();
            // 初始化事件監(jiān)聽器并進行廣播。可以將ApplicationListener監(jiān)聽的事件發(fā)送至相應(yīng)監(jiān)聽器做處理。
            initApplicationEventMulticaster();
            // 實現(xiàn)其他的指定Bean或容器處理, 比如GenericApplicationContext, 可以實現(xiàn)一些自定義UI或Theme。
            onRefresh();
            // 注冊所有實現(xiàn)ApplicationListener接口的監(jiān)聽器, 廣播處理相應(yīng)事件。
            registerListeners();
            //  創(chuàng)建所有非懶加載方式定義單例類。
            finishBeanFactoryInitialization(beanFactory);
            // 完成容器的加載處理, 善后工作, 清除資源緩存, 發(fā)布完成事件等。	
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
            }
            // 銷毀bean信息
            destroyBeans();
            // 復(fù)位 'active'激活標(biāo)志.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        }
        finally {
            // 清除基本緩存信息, 比如方法屬性聲明緩存、標(biāo)注緩存等。	
            resetCommonCaches();
        }
    }
}

? 為Spring 容器初始化的后置處理方法,預(yù)置功能,內(nèi)部為空實現(xiàn)。

? Spring容器啟動完成后, 通知SpringApplicationListener監(jiān)聽數(shù)組,

觸發(fā)容器加載完成started事件, 執(zhí)行監(jiān)聽邏輯。

? 再調(diào)用運行器, 檢查ApplicationContext中有無定義,調(diào)用ApplicationRunner、CommandLineRunner接口的run方法。

最后, 調(diào)用所有定義的SpringApplicationListener監(jiān)聽器,觸發(fā)容器正常運行Running事件, 執(zhí)行監(jiān)聽邏輯。

四、總結(jié)

Spring Boot 能夠極為簡化的開發(fā)與配置, 從啟動流程的研究分析, Spring Boot 做了大量的封裝與自動化處理, 通過掃描Spring Factory 能夠加載各種自動化組件, 同時內(nèi)置了監(jiān)聽器與各種事件, 以及ApplicationRunner啟動器, 具有較強的靈活性與擴展性, Spring Boot 內(nèi)部封裝簡潔, 邏輯清晰,沒有過多的冗余代碼, 能夠起到很好的借鑒學(xué)習(xí)作用。

到此這篇關(guān)于Spring Boot超詳細(xì)分析啟動流程的文章就介紹到這了,更多相關(guān)Spring Boot啟動流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Security權(quán)限管理小結(jié)

    Spring?Security權(quán)限管理小結(jié)

    SpringSecurity是一個權(quán)限管理框架,核心是認(rèn)證和授權(quán),前面已經(jīng)系統(tǒng)的給大家介紹過了認(rèn)證的實現(xiàn)和源碼分析,本文重點來介紹下權(quán)限管理,需要的朋友可以參考下
    2022-08-08
  • Maven配置倉庫的方法步驟

    Maven配置倉庫的方法步驟

    本文主要介紹了Maven配置倉庫的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • java中下拉框select和單選按鈕的回顯操作

    java中下拉框select和單選按鈕的回顯操作

    這篇文章主要介紹了java中下拉框select和單選按鈕的回顯操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 解決Spring在Thread中注入Bean無效的問題

    解決Spring在Thread中注入Bean無效的問題

    這篇文章主要介紹了解決Spring在Thread中注入Bean無效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java listener簡介_動力節(jié)點Java學(xué)院整理

    Java listener簡介_動力節(jié)點Java學(xué)院整理

    這篇文章主要介紹了Java listener簡介,可以用于統(tǒng)計用戶在線人數(shù)等,有興趣的可以了解一下
    2017-07-07
  • 如何設(shè)計一個安全的API接口詳解

    如何設(shè)計一個安全的API接口詳解

    在日常開發(fā)中,總會接觸到各種接口,前后端數(shù)據(jù)傳輸接口,第三方業(yè)務(wù)平臺接口,下面這篇文章主要給大家介紹了關(guān)于如何設(shè)計一個安全的API接口的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • SpringBoot項目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)

    SpringBoot項目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)

    這篇文章主要介紹了SpringBoot項目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • java如何實現(xiàn)post請求webservice服務(wù)端

    java如何實現(xiàn)post請求webservice服務(wù)端

    這篇文章主要介紹了java如何實現(xiàn)post請求webservice服務(wù)端,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot結(jié)合JWT實現(xiàn)用戶登錄、注冊、鑒權(quán)

    SpringBoot結(jié)合JWT實現(xiàn)用戶登錄、注冊、鑒權(quán)

    用戶登錄、注冊及鑒權(quán)是我們基本所有系統(tǒng)必備的,也是很核心重要的一塊,本文主要介紹了SpringBoot結(jié)合JWT實現(xiàn)用戶登錄、注冊、鑒權(quán),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2023-05-05
  • Java雪花算法生成分布式id詳解

    Java雪花算法生成分布式id詳解

    這篇文章主要介紹了Java雪花算法生成分布式id詳解,隨著業(yè)務(wù)的增長,有些表可能要占用很大的物理存儲空間,為了解決該問題,后期使用數(shù)據(jù)庫分片技術(shù),將一個數(shù)據(jù)庫進行拆分,通過數(shù)據(jù)庫中間件連接,需要的朋友可以參考下
    2024-01-01

最新評論