精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SpringBoot的嵌入式Web容器是什么時候加載的?

jf_ro2CN3Fa ? 來源:CSDN ? 2023-07-11 10:10 ? 次閱讀

0.前言

背景:最近有位開發同學說面試被問到Spring Boot 的啟動流程,以及被問到Spring Boot 的嵌入式Web容器是什么時候加載的。如何加載的。是怎么無縫切換的。

這些問題,其實回答起來也是比較復雜的。我們今天就從 SpringApplication.run(EasyPaasAdminApplication.class, args);入口,逐漸向下看下執行流程。來試著回答一下前面這兩個問題。

后面關于SpringBoot 的web容器可以無縫隨意切換為jetty,undertow..這個問題的回答涉及到Spring Boot是如何設計WebServer的。我們后續專門講解一下。

1. 執行邏輯梳理

一般我們SpringBoot 應用的啟動入口都是如下這種固定的寫法,

de939068-1f8a-11ee-962d-dac502259ad0.png

也可以是這樣

publicstaticvoidmain(String[]args){
SpringApplicationapplication=newSpringApplication(MyApplication.class);
//...customizeapplicationsettingshere
application.run(args)
}

但總之,都是使用SpringApplication 調用靜態方法

此方法的注釋

Static helper that can be used to run a SpringApplication from the specified source using default settings.

publicstaticConfigurableApplicationContextrun(ClassprimarySource,String...args){
returnrun(newClass[]{primarySource},args);
}

跟過來就到這,可以看到注釋運行Spring應用程序,創建并刷新一個新的ApplicationContext。

dece32cc-1f8a-11ee-962d-dac502259ad0.pngdeedf9ea-1f8a-11ee-962d-dac502259ad0.png

跟代碼到這兒其實我們對于SpringBoot 的基本啟動流程已經知道了。但是要解答什么時候啟動的Tomcat 還需要繼續分析。

df2549ea-1f8a-11ee-962d-dac502259ad0.png

到這兒我們就可以繼續下去,發現Spring Boot 啟動WebServer。此處的WebServer我就不展開了,可以點擊去就三個方法start ,stop,getPort。可以看出來Spring 在設計接口的時候還是很嚴謹和精簡。

我們的核心脈絡是梳理SpringBoot 啟動過程,并且回答Tomcat 是如何被啟動的。

df49063c-1f8a-11ee-962d-dac502259ad0.png

我們可以看到WebServer 的實現目前內置的有5種。其實Spring Boot 還有一個特性叫做 自動裝配。

這就是為什么5個實現,我們最后啟動的是Tomcat。此處也不做展開。后面我專門搞一個解析SpringBoot 自動裝配的文章。

df7fd20c-1f8a-11ee-962d-dac502259ad0.png

我們看一下內部start 的TomcatWebServer的內部實現。了解過Tomcat 源碼的同學看到這兒就基本明白了。

dfa25a34-1f8a-11ee-962d-dac502259ad0.png

好源碼跟進過程我們到此結束,我們整理和總結一下。

通過掃一遍源碼我們大概可以總結出來如下三個階段

準備階段、應用上下文創建階段、刷新上下文階段。

準備階段 :Spring Boot 會加載應用程序的初始設置,并創建 Spring Boot 上下文。這個階段的核心源碼是 SpringApplication 類的 run() 方法,它會調用 Spring Boot 的各個初始化器進行初始化和準備工作。

應用上下文創建階段 : Spring Boot 會創建應用程序的上下文,包括各種配置信息、Bean 的加載和初始化等。這個階段的核心源碼是 Spring Boot 自動配置機制,通過掃描 classpath 中的配置文件,自動加載和配置各種組件和 Bean。

刷新上下文階段 :Spring Boot 會執行各種啟動任務,包括創建 Web 服務器、加載應用程序的配置、初始化各種組件等。這個階段的核心源碼是 Spring Boot 的刷新機制,它會調用各種初始化器和監聽器,執行各種啟動任務。其中啟動Tomcat 就是在這個環節進行。

2. 核心源碼解析

既然上面我們已經基本上總結除了,Spring Boot的啟動脈絡。也梳理出了一些核心源碼。那么我們對啟動過程的核心源碼解析一下。

2.1. 準備階段

在準備階段中,Spring Boot 會加載應用程序的初始設置,并創建 Spring Boot 上下文。這個階段的核心源碼是 SpringApplication 類的 run() 方法,它會調用 Spring Boot 的各個初始化器進行初始化和準備工作。

publicConfigurableApplicationContextrun(String...args){
//啟動計時器
StopWatchstopWatch=newStopWatch();
stopWatch.start();

//定義應用程序上下文和異常報告器列表
ConfigurableApplicationContextcontext=null;
CollectionexceptionReporters=newArrayList<>();

//配置Headless屬性
configureHeadlessProperty();

//獲取SpringBoot啟動監聽器
SpringApplicationRunListenerslisteners=getRunListeners(args);
//執行啟動監聽器的starting方法
listeners.starting();

try{
//解析命令行參數
ApplicationArgumentsapplicationArguments=newDefaultApplicationArguments(args);
//準備應用程序環境
ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,applicationArguments);
//配置忽略BeanInfo
configureIgnoreBeanInfo(environment);
//打印Banner
BannerprintedBanner=printBanner(environment);
//創建應用程序上下文
context=createApplicationContext();
//獲取異常報告器,關于異常報告,我下次專門講一下SpringBoot 的異常收集器。
exceptionReporters=getSpringFactoriesInstances(SpringBootExceptionReporter.class,newClass[]{ConfigurableApplicationContext.class},context);
//準備應用程序上下文
prepareContext(context,environment,listeners,applicationArguments,printedBanner);
//刷新應用程序上下文
refreshContext(context);
//刷新后操作
afterRefresh(context,applicationArguments);
//停止計時器
stopWatch.stop();
//記錄啟動日志
if(this.logStartupInfo){
newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),stopWatch);
}
//執行啟動監聽器的started方法
listeners.started(context);
//執行Runner
callRunners(context,applicationArguments);
}catch(Throwableex){
//處理啟動失敗
handleRunFailure(context,ex,exceptionReporters,listeners);
thrownewIllegalStateException(ex);
}

try{
//執行啟動監聽器的running方法
listeners.running(context);
}catch(Throwableex){
//處理啟動失敗
handleRunFailure(context,ex,exceptionReporters,null);
thrownewIllegalStateException(ex);
}

//返回應用程序上下文
returncontext;
}

在 run() 方法中,Spring Boot 首先會創建一個 StopWatch 對象,用于記錄整個啟動過程的耗時。然后,Spring Boot 會調用 getRunListeners(args) 方法獲取 Spring Boot 的各個啟動監聽器,并調用starting() 方法通知這些監聽器啟動過程已經開始。接著調用 prepareEnvironment(listeners, applicationArguments) 方法創建應用程序的環境變量。

這個方法會根據用戶的配置和默認設置創建一個 ConfigurableEnvironment對象,并將其傳給后面的 createApplicationContext() 方法。printBanner(environment) 方法打印啟動界面的 Banner,調用 refreshContext(context)方法刷新上下文。這個方法會啟動上下文,執行各種啟動任務,包括創建 Web 服務器、加載應用程序的配置、初始化各種組件等。具體的啟動任務會在刷新上下文階段中進行。

2.2. 應用上下文創建階段

在應用上下文創建階段中,Spring Boot 會創建應用程序的上下文,包括各種配置信息、Bean 的加載和初始化等。這個階段的核心源碼是 Spring Boot 自動配置機制,通過掃描 classpath 中的配置文件,自動加載和配置各種組件和 Bean。

protectedConfigurableApplicationContextcreateApplicationContext(){
ClasscontextClass=this.applicationContextClass;
if(contextClass==null){
try{
switch(this.webApplicationType){
caseSERVLET:
contextClass=Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
caseREACTIVE:
contextClass=Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass=Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch(ClassNotFoundExceptionex){
thrownewIllegalStateException(
"UnabletocreateadefaultApplicationContext,"+
"pleasespecifyanApplicationContextClass",ex);
}
}
return(ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}

在 createApplicationContext() 方法中,Spring Boot 首先會判斷應用程序的類型,如果是 Web 應用程序,則會創建一個 WebApplicationContext;否則,會創建一個普通的 ApplicationContext。調用 BeanUtils.instantiateClass(contextClass) 方法創建應用程序的上下文。這個方法會根據上面的邏輯創建一個相應的 ApplicationContext。調用 load() 方法加載應用程序的配置。

這個方法會掃描 classpath 中的各種配置文件,例如 application.properties、application.yml、META-INF/spring.factories 等,自動配置各種組件和 Bean。調用 postProcessApplicationContext() 方法對應用程序的上下文進行后處理。這個方法會調用各種初始化器和監聽器,執行各種初始化任務。

2.3. 刷新上下文階段

在刷新上下文階段中,Spring Boot 會執行各種啟動任務,包括創建 Web 服務器(剛才我們跟源碼的時候也看到了,如上我的截圖)、加載應用程序的配置、初始化各種組件等。這個階段的核心源碼是 Spring Boot 的刷新機制,它會調用各種初始化器和監聽器,執行各種啟動任務。

protectedvoidrefreshContext(ConfigurableApplicationContextapplicationContext){
refresh(applicationContext);
if(this.registerShutdownHook){
try{
applicationContext.registerShutdownHook();
}
catch(AccessControlExceptionex){
//Notallowedinsomeenvironments.
}
}
}

在 refreshContext() 方法中調用 refresh(applicationContext) 方法刷新上下文。這個方法是 ApplicationContext 接口的核心方法,會啟動上下文,執行各種啟動任務。調用 registerShutdownHook() 方法注冊應用程序的關閉鉤子。這個方法會在應用程序關閉時自動執行,清理資源、關閉線程等,所以我們利用此特性在服務關閉的時候清理一些資源。并向外部發送告警通知。

在 refresh(applicationContext) 方法中,Spring Boot 會執行上下文的各種啟動任務,包括創建 Web 服務器、加載應用程序的配置、初始化各種組件等。具體的啟動任務會調用各種初始化器和監聽器,例如:

for(ApplicationContextInitializerinitializer:getInitializers()){
initializer.initialize(applicationContext);
}

另外,Spring Boot 還會調用各種監聽器,我們不做贅述,例如:

for(ApplicationListenerlistener:getApplicationListeners()){
if(listenerinstanceofSmartApplicationListener){
SmartApplicationListenersmartListener=(SmartApplicationListener)listener;
if(smartListener.supportsEventType(eventType)
&&smartListener.supportsSourceType(sourceType)){
invokeListener(smartListener,event);
}
}
elseif(supportsEvent(listener,eventType)){
invokeListener(listener,event);
}
}

基本上就是這些了。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5068

    文章

    19019

    瀏覽量

    303291
  • Web服務器
    +關注

    關注

    0

    文章

    138

    瀏覽量

    24371
  • tomcat
    +關注

    關注

    0

    文章

    27

    瀏覽量

    4845
  • SpringBoot
    +關注

    關注

    0

    文章

    173

    瀏覽量

    169

原文標題:三分鐘了解 SpringBoot 的啟動流程

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    SpringBoot嵌入式Web容器有哪幾種呢

    種類1.servlett web容器,2.reactive web容器spring-boot支持使用jetty、netty、tomcat、undertow作為
    發表于 12-16 06:51

    談一談Spring Boot嵌入式Web容器

    Spring Boot嵌入式Web容器Embedded Tomcatorg.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerorg.
    發表于 12-16 08:16

    Spring Boot嵌入式Web容器原理是什么

    Spring Boot嵌入式Web容器原理Spring Boot的目標是構建“非常容易創建、獨立、產品級別的基于Spring的應用”。這些應用是“立即可運行的”。在這個過程中,完全沒有代碼生成
    發表于 12-16 07:57

    SpringBoot嵌入式Servlet容器啟動原理是什么

    SpringBoot嵌入式Servlet容器啟動原理思維導圖
    發表于 12-20 07:26

    嵌入式Servlet容器啟動原理是什么

    一、SpringBoot應用啟動運行run方法二、run方法調用了refreshContext(context);SpringBoot刷新IOC容器【創建IOC容器對象,并初始化
    發表于 12-20 07:54

    SpringBoot應用啟動運行run方法

    什么時候創建嵌入式的Servlet容器工廠?什么時候獲取嵌入式的Servlet容器并啟動Tomc
    發表于 12-20 06:16

    嵌入式Servlet容器自動配置原理是什么

    這一節課我們來說一說嵌入式Servlet容器自動配置原理前面我們都知道怎么去配置容器參數,切換容器,但是我們不知道springboot自動配
    發表于 12-20 06:29

    如何配置嵌入式的Servlet容器

    以前的web應用開發我們采取的方式是項目完成后打包成war包,然后配置tomcat啟動運行項目,而Spring Boot默認使用的是嵌入式的tomcat,那我們需要如何配置嵌入式的Servlet
    發表于 12-20 07:18

    SpringBoot配置嵌入式Servlet

    SpringBoot配置嵌入式Servlet容器定制和修改Servlet容器相關配置全局配置文件編寫WebServerFactoryCustomizer注冊Servlet三大組件注冊S
    發表于 12-20 06:19

    什么時候獲取嵌入式的Servlet容器并啟動Tomcat

    什么時候創建嵌入式的Servlet容器工廠?什么時候獲取嵌入式的Servlet容器并啟動Tomc
    發表于 12-20 06:11

    如何對嵌入式Servlet容器進行配置呢

    一、配置嵌入式Servlet容器SpringBoot默認使用Tomcat作為嵌入式的Servlet容器;1、定制和修改Servlet
    發表于 12-21 06:09

    嵌入式Servlet容器啟動原理

    SpringBoot源碼學習系列之嵌入式Servlet容器啟動原理SpringBoot的自動配置就是SpringBoot的精髓所在,對于
    發表于 12-22 07:23

    如何配置嵌入式Servlet容器

    springboot默認使用的是嵌入式的servlet容器(tomcat):定制和修改servlet容器的相關配置1)修改和server有關的配置(ServerProperties類
    發表于 12-24 06:56

    嵌入式引導加載技術

    嵌入式引導加載技術
    發表于 02-08 01:37 ?10次下載

    嵌入式Servlet容器

    配置嵌入式Servlet容器##Spring Boot里面內置了嵌入式的Servlet容器(tomcat)點擊pom.xml->右鍵->Diagrams->show
    發表于 10-20 17:51 ?3次下載
    <b class='flag-5'>嵌入式</b>Servlet<b class='flag-5'>容器</b>