深入理解Spring Boot啟動順序

一、Spring Boot啟動流程

在了解Spring Boot的啟動順序之前,我們需要先了解Spring Boot的啟動流程。在Spring Boot啟動時,會以SpringApplication為入口進行啟動。SpringApplication會開啟一些基本的事件(ApplicationEvent),並將這些事件發送給所有註冊了相應監聽器(ApplicationListener)的組件進行處理。

因此,Spring Boot的啟動流程可以概括為以下幾步:

  1. 創建SpringApplication
  2. 執行SpringApplication的run()方法
  3. SpringApplication會依次發布以下事件:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent、ApplicationFailedEvent
  4. 所有註冊了相應的監聽器會處理它們感興趣的事件

二、Spring Boot啟動順序

1. SpringApplication構造函數

在創建SpringApplication實例的時候,Spring Boot會進行相關的初始化和準備階段。在這個過程中,Spring Boot會根據一些默認設置來決定要使用哪些特性,並對這些特性進行配置。比如,自動配置、Profile、配置文件等。

示例代碼

@SpringBootApplication
public class SpringApplicationDemo {
  public static void main(String[] args) {
    SpringApplication application = new SpringApplication(SpringApplicationDemo.class);
    application.run(args);
  }
}

2. ApplicationStartingEvent

在調用SpringApplication的run()方法之前,SpringApplication會發布ApplicationStartingEvent事件。這個事件表示SpringApplication即將啟動。在這個事件中,我們可以進行一些相關的操作,比如輸出程序啟動日誌。

示例代碼

@Component
public class StartingEventListener implements ApplicationListener<ApplicationStartingEvent> {
  private static final Logger LOGGER = LoggerFactory.getLogger(StartingEventListener.class);

  @Override
  public void onApplicationEvent(ApplicationStartingEvent event) {
    LOGGER.info("Application is starting with args: {}",
        Arrays.toString(event.getArgs()));
  }
}

3. ApplicationEnvironmentPreparedEvent

在執行run()方法之前,SpringApplication會發布ApplicationEnvironmentPreparedEvent事件。在這個事件中,我們可以對應用程序的環境進行一些自定義配置,比如添加自定義屬性、配置環境變數等。

示例代碼

@Component
public class EnvironmentPreparedEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
  @Override
  public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
    ConfigurableEnvironment environment = event.getEnvironment();
    Map<String, Object> properties = new HashMap();
    properties.put("server.port", 8081);
    PropertiesPropertySource propertySource = new PropertiesPropertySource("customProperties", properties);
    environment.getPropertySources().addFirst(propertySource);
  }
}

4. ApplicationContextInitializedEvent

在執行run()方法時,Spring Boot會發布ApplicationContextInitializedEvent事件。這個事件表示ApplicationContext正在被創建,但是還沒有載入任何Bean。在這個事件中,我們可以手動往ApplicationContext中添加一些Bean。

示例代碼

@Component
public class ContextInitializedEventListener implements ApplicationListener<ApplicationContextInitializedEvent> {
  @Override
  public void onApplicationEvent(ApplicationContextInitializedEvent event) {
    ConfigurableApplicationContext context = event.getApplicationContext();
    context.getBeanFactory().registerSingleton("myBean", new Object());
  }
}

5. ApplicationPreparedEvent

在上一步中,ApplicationContext成功創建並載入了所有的Bean。在執行run()方法之前,Spring Boot會發布ApplicationPreparedEvent事件。在這個事件中,我們可以獲取ApplicationContext,並進行一些自定義配置。

示例代碼

@Component
public class PreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {
  @Override
  public void onApplicationEvent(ApplicationPreparedEvent event) {
    ConfigurableApplicationContext context = event.getApplicationContext();
    DataSource dataSource = context.getBean(DataSource.class);
    try {
      dataSource.getConnection().close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}

6. ApplicationStartedEvent

在上一步結束後,ApplicationContext會被刷新,並啟動完成。在這個時候,Spring Boot會發布ApplicationStartedEvent事件。在這個事件中,我們可以進行一些啟動後的操作,比如數據初始化。

示例代碼

@Component
public class StartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
  private static final Logger LOGGER = LoggerFactory.getLogger(StartedEventListener.class);

  @Override
  public void onApplicationEvent(ApplicationStartedEvent event) {
    LOGGER.info("Application has started...");
  }
}

7. ApplicationReadyEvent

當應用程序啟動並且ApplicationContext中的Bean都已經裝配好之後,Spring Boot會發布ApplicationReadyEvent事件,這個事件表示此時應用程序已經準備好了。我們可以在這種情況下進行一些定時任務的啟動、消息的處理等操作。

示例代碼

@Component
public class ReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {
  @Override
  public void onApplicationEvent(ApplicationReadyEvent event) {
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("I'm a TimerTask!");
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 5000L);
  }
}

8. ApplicationFailedEvent

如果應用程序啟動失敗,Spring Boot會發布ApplicationFailedEvent事件,這個事件表示應用程序啟動過程中出現了錯誤。在這個事件中我們可以獲取到失敗的原因,並進行相應的處理。

示例代碼

@Component
public class FailedEventListener implements ApplicationListener<ApplicationFailedEvent> {
  @Override
  public void onApplicationEvent(ApplicationFailedEvent event) {
    Throwable throwable = event.getException();
    LOGGER.error("Application failed to start: {}", throwable.getMessage());
  }
}

三、總結

通過本文的介紹,我們可以詳細了解Spring Boot啟動順序背後的機制和原理。在實際開發中,我們可以根據自己的需求選擇合適的時間點進行自定義操作,從而達到更加優美的應用啟動順序。

原創文章,作者:DMJXT,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/370404.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
DMJXT的頭像DMJXT
上一篇 2025-04-22 01:14
下一篇 2025-04-22 01:14

相關推薦

發表回復

登錄後才能評論