最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot從main方法到內(nèi)嵌Tomcat的全過(guò)程(自動(dòng)化流程)

 更新時(shí)間:2025年07月22日 11:40:53   作者:程序員Meteor  
SpringBoot啟動(dòng)始于main方法,創(chuàng)建SpringApplication實(shí)例,初始化上下文,準(zhǔn)備環(huán)境,刷新容器并啟動(dòng)內(nèi)嵌Tomcat,通過(guò)自動(dòng)配置加載必要類完成應(yīng)用部署,本文給大家介紹Spring Boot從main方法到內(nèi)嵌Tomcat的全過(guò)程,感興趣的朋友一起看看吧

Spring Boot的啟動(dòng)過(guò)程是一個(gè)精心設(shè)計(jì)的自動(dòng)化流程,下面我將詳細(xì)闡述從main方法開(kāi)始到內(nèi)嵌Tomcat啟動(dòng)的全過(guò)程。

1. 入口:main方法

一切始于一個(gè)簡(jiǎn)單的main方法:

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

2. SpringApplication初始化

SpringApplication.run()方法內(nèi)部會(huì)創(chuàng)建一個(gè)SpringApplication實(shí)例:

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return new SpringApplication(primarySource).run(args);
}

2.1 構(gòu)造階段

在SpringApplication構(gòu)造函數(shù)中完成以下關(guān)鍵操作:

  • 推斷應(yīng)用類型:判斷是Servlet應(yīng)用(Spring MVC)還是Reactive應(yīng)用(Spring WebFlux)
  • 加載ApplicationContextInitializer:通過(guò)META-INF/spring.factories加載
  • 加載ApplicationListener:同樣通過(guò)spring.factories機(jī)制加載
  • 推斷主配置類:通過(guò)堆棧分析找到包含main方法的類

3. 運(yùn)行階段:run()方法

run()方法是整個(gè)啟動(dòng)過(guò)程的核心:

public ConfigurableApplicationContext run(String... args) {
    // 1. 創(chuàng)建并啟動(dòng)計(jì)時(shí)器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    // 2. 初始化應(yīng)用上下文和異常報(bào)告器
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    // 3. 獲取SpringApplicationRunListeners并啟動(dòng)
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        // 4. 準(zhǔn)備環(huán)境
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        // 5. 打印Banner
        Banner printedBanner = printBanner(environment);
        // 6. 創(chuàng)建應(yīng)用上下文
        context = createApplicationContext();
        // 7. 準(zhǔn)備應(yīng)用上下文
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 8. 刷新應(yīng)用上下文(關(guān)鍵步驟)
        refreshContext(context);
        // 9. 刷新后處理
        afterRefresh(context, applicationArguments);
        // 10. 停止計(jì)時(shí)器并發(fā)布啟動(dòng)完成事件
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        // 11. 執(zhí)行Runner
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

4. 創(chuàng)建應(yīng)用上下文

createApplicationContext()方法根據(jù)應(yīng)用類型創(chuàng)建不同的應(yīng)用上下文:

  • Servlet環(huán)境:創(chuàng)建AnnotationConfigServletWebServerApplicationContext
  • Reactive環(huán)境:創(chuàng)建AnnotationConfigReactiveWebServerApplicationContext
  • 普通環(huán)境:創(chuàng)建AnnotationConfigApplicationContext

對(duì)于Web應(yīng)用,會(huì)創(chuàng)建AnnotationConfigServletWebServerApplicationContext,它繼承自ServletWebServerApplicationContext。

5. 準(zhǔn)備應(yīng)用上下文

prepareContext()方法完成以下工作:

  • 將環(huán)境綁定到上下文
  • 后置處理上下文
  • 應(yīng)用所有初始化器
  • 發(fā)布ContextPrepared事件
  • 注冊(cè)主配置類bean定義
  • 發(fā)布ContextLoaded事件

6. 刷新應(yīng)用上下文

refreshContext()最終調(diào)用AbstractApplicationContext.refresh(),這是Spring容器的核心刷新流程:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 準(zhǔn)備刷新
        prepareRefresh();
        // 2. 獲取新的BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 3. 準(zhǔn)備BeanFactory
        prepareBeanFactory(beanFactory);
        try {
            // 4. 后置處理BeanFactory
            postProcessBeanFactory(beanFactory);
            // 5. 調(diào)用BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);
            // 6. 注冊(cè)BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            // 7. 初始化MessageSource
            initMessageSource();
            // 8. 初始化事件廣播器
            initApplicationEventMulticaster();
            // 9. 初始化特殊bean(由子類實(shí)現(xiàn))
            onRefresh();
            // 10. 注冊(cè)監(jiān)聽(tīng)器
            registerListeners();
            // 11. 初始化所有非懶加載單例
            finishBeanFactoryInitialization(beanFactory);
            // 12. 完成刷新
            finishRefresh();
        }
        catch (BeansException ex) {
            // 處理異常...
        }
    }
}

7. 內(nèi)嵌Tomcat啟動(dòng)的關(guān)鍵:onRefresh()

對(duì)于Servlet Web應(yīng)用,ServletWebServerApplicationContext重寫(xiě)了onRefresh()方法:

protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    }
    catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}

createWebServer()是內(nèi)嵌服務(wù)器啟動(dòng)的關(guān)鍵:

private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        // 1. 獲取WebServer工廠(Tomcat, Jetty或Undertow)
        ServletWebServerFactory factory = getWebServerFactory();
        // 2. 創(chuàng)建WebServer
        this.webServer = factory.getWebServer(getSelfInitializer());
    }
    else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context", ex);
        }
    }
    initPropertySources();
}

8. Tomcat服務(wù)器創(chuàng)建過(guò)程

以Tomcat為例,TomcatServletWebServerFactory.getWebServer()方法:

public WebServer getWebServer(ServletContextInitializer... initializers) {
    // 1. 創(chuàng)建Tomcat實(shí)例
    Tomcat tomcat = new Tomcat();
    // 2. 配置基礎(chǔ)目錄
    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    // 3. 配置連接器
    Connector connector = new Connector(this.protocol);
    connector.setThrowOnFailure(true);
    tomcat.getService().addConnector(connector);
    customizeConnector(connector);
    tomcat.setConnector(connector);
    // 4. 配置Host
    tomcat.getHost().setAutoDeploy(false);
    configureEngine(tomcat.getEngine());
    // 5. 準(zhǔn)備上下文
    prepareContext(tomcat.getHost(), initializers);
    // 6. 創(chuàng)建TomcatWebServer并啟動(dòng)
    return getTomcatWebServer(tomcat);
}

9. 啟動(dòng)Tomcat

TomcatWebServer構(gòu)造函數(shù)中完成Tomcat的啟動(dòng):

public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
    this.tomcat = tomcat;
    this.autoStart = autoStart;
    initialize();
}
private void initialize() throws WebServerException {
    // 啟動(dòng)Tomcat
    this.tomcat.start();
    // 啟動(dòng)一個(gè)守護(hù)線程來(lái)等待停止命令
    startDaemonAwaitThread();
}

10. 自動(dòng)配置的關(guān)鍵

整個(gè)過(guò)程中,自動(dòng)配置是通過(guò)@SpringBootApplication注解中的@EnableAutoConfiguration實(shí)現(xiàn)的:

  • invokeBeanFactoryPostProcessors()階段會(huì)處理自動(dòng)配置
  • AutoConfigurationImportSelector會(huì)加載META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中的配置類
  • 對(duì)于Tomcat,會(huì)加載ServletWebServerFactoryAutoConfiguration
  • 這個(gè)配置類通過(guò)@Import引入了EmbeddedTomcat等配置

總結(jié)流程

  1. 啟動(dòng)main方法
  2. 創(chuàng)建SpringApplication實(shí)例
  3. 運(yùn)行run()方法
  4. 準(zhǔn)備環(huán)境
  5. 創(chuàng)建應(yīng)用上下文(AnnotationConfigServletWebServerApplicationContext)
  6. 準(zhǔn)備上下文(注冊(cè)配置類等)
  7. 刷新上下文(核心)
    • 調(diào)用onRefresh()
    • 創(chuàng)建內(nèi)嵌Web服務(wù)器(Tomcat)
    • 啟動(dòng)Tomcat
  8. 發(fā)布啟動(dòng)完成事件
  9. 執(zhí)行Runner

到此這篇關(guān)于Spring Boot從main方法到內(nèi)嵌Tomcat的全過(guò)程(自動(dòng)化流程)的文章就介紹到這了,更多相關(guān)Spring Boot啟動(dòng)過(guò)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA運(yùn)行java程序時(shí)總彈出提示配置Edit Configurations問(wèn)題

    IDEA運(yùn)行java程序時(shí)總彈出提示配置Edit Configurations問(wèn)題

    更新IDEA后,運(yùn)行Java程序時(shí)可能需要手動(dòng)配置JDK版本,通過(guò)統(tǒng)一設(shè)置默認(rèn)JDK可以解決每次彈出EditConfigurations的問(wèn)題,此操作可以簡(jiǎn)化開(kāi)發(fā)流程,提高效率
    2024-09-09
  • 深入剖析Java工廠模式讓你的代碼更靈活

    深入剖析Java工廠模式讓你的代碼更靈活

    Java工廠模式是一種創(chuàng)建對(duì)象的設(shè)計(jì)模式,它可以在不暴露對(duì)象創(chuàng)建邏輯的情況下,將對(duì)象的創(chuàng)建委托給子類或者其他對(duì)象。本文就來(lái)深入剖析一下Java工廠模式是如何讓你的代碼更靈活、可擴(kuò)展、易維護(hù)的
    2023-05-05
  • Java API操作HDFS方法詳細(xì)講解

    Java API操作HDFS方法詳細(xì)講解

    這篇文章主要介紹了Java API操作Hdfs詳細(xì)示例,遍歷當(dāng)前目錄下所有文件與文件夾,可以使用listStatus方法實(shí)現(xiàn)上述需求,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Java設(shè)計(jì)模式之橋接模式

    Java設(shè)計(jì)模式之橋接模式

    這篇文章介紹了Java設(shè)計(jì)模式之橋接模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 關(guān)于Java的二叉樹(shù)、紅黑樹(shù)、B+樹(shù)詳解

    關(guān)于Java的二叉樹(shù)、紅黑樹(shù)、B+樹(shù)詳解

    這篇文章主要介紹了關(guān)于Java的二叉樹(shù)、紅黑樹(shù)、B+樹(shù)詳解,能同時(shí)具備數(shù)組查找快的優(yōu)點(diǎn)以及鏈表插入和刪除快的優(yōu)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)就是樹(shù),需要的朋友可以參考下
    2023-05-05
  • SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn)

    SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn)

    Spring Cloud Gateway 作為網(wǎng)關(guān)層,承擔(dān)著請(qǐng)求轉(zhuǎn)發(fā)、權(quán)限校驗(yàn)等重要職責(zé),本文主要介紹了SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • Java?Web實(shí)現(xiàn)類似Excel表格鎖定功能實(shí)戰(zhàn)教程

    Java?Web實(shí)現(xiàn)類似Excel表格鎖定功能實(shí)戰(zhàn)教程

    本文將詳細(xì)介紹通過(guò)創(chuàng)建特定div元素并利用CSS布局和JavaScript事件監(jiān)聽(tīng)來(lái)實(shí)現(xiàn)類似Excel的鎖定行和列效果的方法,感興趣的朋友跟隨小編一起看看吧
    2025-06-06
  • 全面匯總SpringBoot和SpringClould常用注解

    全面匯總SpringBoot和SpringClould常用注解

    Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說(shuō)明、配置的功能,這篇文章就帶你來(lái)了解一下
    2021-08-08
  • Java序列化和反序列化_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java序列化和反序列化_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    把對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化,把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化。接下來(lái)通過(guò)本文給大家介紹Java序列化和反序列化及主要的兩種用途,感興趣的的友參考下吧
    2017-05-05
  • java通過(guò)復(fù)選框控件數(shù)組實(shí)現(xiàn)添加多個(gè)復(fù)選框控件示例分享

    java通過(guò)復(fù)選框控件數(shù)組實(shí)現(xiàn)添加多個(gè)復(fù)選框控件示例分享

    編寫(xiě)程序,通過(guò)復(fù)選框控件數(shù)組事先選擇用戶愛(ài)好信息的復(fù)選框,在該程序中,要求界面中的復(fù)選框數(shù)量可以根據(jù)指定復(fù)選框名稱的字符串?dāng)?shù)組的長(zhǎng)度來(lái)自動(dòng)調(diào)節(jié)
    2014-02-02

最新評(píng)論

泰宁县| 乌恰县| 航空| 新营市| 视频| 高尔夫| 德阳市| 元谋县| 南康市| 正宁县| 晋江市| 扎囊县| 莆田市| 绥阳县| 敖汉旗| 巴里| 通山县| 丁青县| 镇原县| 曲松县| 电白县| 日喀则市| 来宾市| 钟祥市| 芦山县| 高安市| 时尚| 韶关市| 揭阳市| 来宾市| 阿荣旗| 中江县| 台安县| 桦南县| 阿克苏市| 吉水县| 阿合奇县| 巴东县| 石景山区| 泽普县| 池州市|