1. 程式人生 > >【Spring boot學習】事件啟動順序

【Spring boot學習】事件啟動順序

ApplicationStartedEvent事件,所以在2.0版本中所有的事件按執行的先後順序如下:

  • ApplicationStartingEvent
  • ApplicationEnvironmentPreparedEvent
  • ApplicationPreparedEvent
  • ApplicationStartedEvent <= 新增的事件
  • ApplicationReadyEvent
  • ApplicationFailedEvent

從上面的列表中,我們可以看到ApplicationStartedEvent位於ApplicationPreparedEvent之後,ApplicationReadyEvent

之前。

下面我們通過程式碼的方式來直觀的感受這個事件的切入位置,以便與將來我們在這個切入點加入自己需要的邏輯。

第一步:我們可以編寫ApplicationPreparedEventApplicationStartedEvent以及ApplicationReadyEvent三個事件的監聽器,然後在這三個事件觸發的時候列印一些日誌來觀察它們各自的切入點,比如:

@Slf4j
public class ApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event) {
        log.info("......ApplicationPreparedEvent......");
    }

}

@Slf4j
public class ApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        log.info("......ApplicationStartedEvent......");
    }

}

@Slf4j
public class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("......ApplicationReadyEvent......");
    }

}

第二步:在/src/main/resources/目錄下新建:META-INF/spring.factories配置檔案,通過配置org.springframework.context.ApplicationListener來載入上面我們編寫的監聽器。

org.springframework.context.ApplicationListener=
  com.didispace.ApplicationPreparedEventListener,\
  com.didispace.ApplicationReadyEventListener,\
  com.didispace.ApplicationStartedEventListener

此時,我們執行Spring Boot應用可以獲得類似如下日誌輸出:

下面可以看看官方文件對ApplicationStartedEventApplicationReadyEvent的解釋:從日誌中我們可以看到清晰的看到ApplicationPreparedEventApplicationStartedEvent以及ApplicationReadyEvent三個事件的切入點。通過這個例子可能讀者會感到疑問:ApplicationStartedEventApplicationReadyEvent從事件命名和日誌輸出位置來看,都是應用載入完成之後的事件,它們是否有什麼區別呢?

An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.An ApplicationReadyEvent is sent after any application and command-line runners have been called. It indicates that the application is ready to service requests

從文件中我們可以知道他們兩中間還有一個過程就是command-line runners被呼叫的內容。所以,為了更準確的感受這兩個事件的區別,我們在應用主類中加入CommandLineRunner的實現,比如:

@Slf4j
@SpringBootApplication
public class Application {

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

    @Bean
    public DataLoader dataLoader() {
        return new DataLoader();
    }

    @Slf4j
    static class DataLoader implements CommandLineRunner {

        @Override
        public void run(String... strings) throws Exception {
            log.info("Loading data...");
        }
    }

}

最後,我們再執行程式,此時我們可以發現這兩個事件中間輸出了上面定義的DataLoader的輸出內容,具體如下:

2018-03-07 18:15:20.845  INFO 83387 --- [main] c.d.ApplicationStartedEventListener      : ......ApplicationStartedEvent......
2018-03-07 18:15:20.846  INFO 83387 --- [main] com.didispace.Application$DataLoader     : Loading data...
2018-03-07 18:15:20.847  INFO 83387 --- [main] c.d.ApplicationReadyEventListener        : ......ApplicationReadyEvent......zhua