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

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

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

Spring Boot的啟動過程是一個精心設計的自動化流程,下面我將詳細闡述從main方法開始到內(nèi)嵌Tomcat啟動的全過程。

1. 入口:main方法

一切始于一個簡單的main方法:

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

2. SpringApplication初始化

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

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

2.1 構(gòu)造階段

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

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

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

run()方法是整個啟動過程的核心:

public ConfigurableApplicationContext run(String... args) {
    // 1. 創(chuàng)建并啟動計時器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    // 2. 初始化應用上下文和異常報告器
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    // 3. 獲取SpringApplicationRunListeners并啟動
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        // 4. 準備環(huán)境
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        // 5. 打印Banner
        Banner printedBanner = printBanner(environment);
        // 6. 創(chuàng)建應用上下文
        context = createApplicationContext();
        // 7. 準備應用上下文
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 8. 刷新應用上下文(關鍵步驟)
        refreshContext(context);
        // 9. 刷新后處理
        afterRefresh(context, applicationArguments);
        // 10. 停止計時器并發(fā)布啟動完成事件
        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)建應用上下文

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

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

對于Web應用,會創(chuàng)建AnnotationConfigServletWebServerApplicationContext,它繼承自ServletWebServerApplicationContext

5. 準備應用上下文

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

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

6. 刷新應用上下文

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

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

7. 內(nèi)嵌Tomcat啟動的關鍵:onRefresh()

對于Servlet Web應用,ServletWebServerApplicationContext重寫了onRefresh()方法:

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

createWebServer()是內(nèi)嵌服務器啟動的關鍵:

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服務器創(chuàng)建過程

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

public WebServer getWebServer(ServletContextInitializer... initializers) {
    // 1. 創(chuàng)建Tomcat實例
    Tomcat tomcat = new Tomcat();
    // 2. 配置基礎目錄
    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. 準備上下文
    prepareContext(tomcat.getHost(), initializers);
    // 6. 創(chuàng)建TomcatWebServer并啟動
    return getTomcatWebServer(tomcat);
}

9. 啟動Tomcat

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

public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
    this.tomcat = tomcat;
    this.autoStart = autoStart;
    initialize();
}
private void initialize() throws WebServerException {
    // 啟動Tomcat
    this.tomcat.start();
    // 啟動一個守護線程來等待停止命令
    startDaemonAwaitThread();
}

10. 自動配置的關鍵

整個過程中,自動配置是通過@SpringBootApplication注解中的@EnableAutoConfiguration實現(xiàn)的:

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

總結(jié)流程

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

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

相關文章

  • IDEA運行java程序時總彈出提示配置Edit Configurations問題

    IDEA運行java程序時總彈出提示配置Edit Configurations問題

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

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

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

    Java API操作HDFS方法詳細講解

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

    Java設計模式之橋接模式

    這篇文章介紹了Java設計模式之橋接模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 關于Java的二叉樹、紅黑樹、B+樹詳解

    關于Java的二叉樹、紅黑樹、B+樹詳解

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

    SpringCloud Gateway 權限認證的實現(xiàn)

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

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

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

    全面匯總SpringBoot和SpringClould常用注解

    Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能,這篇文章就帶你來了解一下
    2021-08-08
  • Java序列化和反序列化_動力節(jié)點Java學院整理

    Java序列化和反序列化_動力節(jié)點Java學院整理

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

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

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

最新評論

出国| 弥勒县| 清新县| 钦州市| 皋兰县| 新泰市| 宜君县| 辽源市| 科技| 永宁县| 工布江达县| 绥江县| 普兰县| 阿瓦提县| 临沂市| 阿克| 刚察县| 奇台县| 蒙山县| 慈溪市| 毕节市| 宜宾县| 长丰县| 涿鹿县| 大田县| 石景山区| 汨罗市| 万全县| 阿拉善右旗| 沅江市| 通海县| 历史| 河曲县| 宁德市| 新兴县| 泸西县| 阿图什市| 剑阁县| 萨迦县| 黑龙江省| 松溪县|