springboot 項目容器啟動後如何自動執行指定方法

springboot 項目容器啟動後自動執行指定

我們需要寫一個class去讓它實現ApplicationRunner,然後重寫它的run方法就行瞭,註意類加上@Component註解

註意:這個class需要寫在和Application啟動類的同級目錄或者子級目錄下,否則不生效。

代碼:

package com.qq.weixin; 
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
 
/**
 * @author XuYangWei
 * @Date 2021/1/22 8:56
 */
@Slf4j
@Component
public class TestRuner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        log.info("我是Spring容器啟動後立即執行的方法,當前時間:"+ DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
    }
}

springboot-容器及啟動過程

SpringBoot會啟動兩個容器,即父子容器

  • 父容器(Spring容器):AnnotationConfigWebApplicationContex
  • 子容器(SpringMVC容器):AnnotationConfigEmbeddedWebApplicationContex

思考幾個問題:

問題1:為什麼要啟動父子兩個容器?

在Spring整體框架的核心概念中,容器是核心思想,而在一個項目中,容器不一定隻有一個,Spring中可以包括多個容器,使用上下層關系來管理容器可以解決公共屬性抽取的問題,即將公共的屬性放到父容器中,對其各個子容器均可見,實現瞭復用功能,註意子容器對父容器是不可見的。

問題2:在什麼時候啟動父容器?

準備環境變量,即執行prepareEnvironment方法時,發佈ApplicationEnvironmentPreparedEvent事件,BootstrapApplicationListener監聽器收到該事件,會初始化父容器

問題3:父容器和子容器的區別?

1.子容器中會創建植入的tomcat容器類,用來管理tomcat服務,父容器沒有

2.父容器管理的bean集合是spring框架內置的一些bean,子容器管理的bean集合是我們業務定義的bean以及spring框架內置的bean

問題4:怎麼保證父容器啟動過程中

執行prepareEnvironment方法時,BootstrapApplicationListener監聽器不再重復執行?

父容器初始化完成後,會在webEnvironment屬性中加入bootstrap屬性標識,這樣就可以根據該標識來判斷是否需要執行瞭

問題5:容器實際通過什麼來管理bean

容器通過beanFactory來管理對象,父子容器都會各持有一個DefaultListableBeanFactory,即父子容器都會管理各自的bean。

子容器啟動流程:

1.執行初始化:初始化webEnvironment以及listeners

2.發佈容器啟動事件

3.在執行prepareEnvironment步驟時,發佈ApplicationEnvironmentPreparedEvent事件,BootstrapApplicationListener監聽器收到該事件,會再次調用SpringApplication

  • 初始化和run方法(初始化父容器的步驟類似子容器)

4.創建context,通過判斷webEnvironment標識,這時為true,創建AnnotationConfigEmbeddedWebApplicationContext實例

5.執行refreshContext,比較核心的方法,詳細說一下:

  • 獲取bean工廠,即創建DefaultListableBeanFactory實例
  • 為bean工廠賦一些基礎屬性,主要有類加載器
  • 為bean工廠註冊WebApplicationContextServletContextAwareProcessor,一個BeanPostProcessor,主要用於獲取ServletContext
  • 執行beanFactoryPostProcessor,遞歸處理,主要用於掃描@CompontScan、@Import、@ImportSource等註解的類,首先註冊bean元數據到工廠,然後可以修改bean工廠
  • 實例化BeanPostProcessor類並註冊到bean工廠單例列表中
  • 實例化消息通知類並註冊到bean工廠單例列表中
  • 調用onRefresh方法,初始化一個植入的tomcat容器
  • 註冊監聽器到消息通知器中,區分為兩類:一、從系統配置中加載的監聽器(已實例化) 二、已註冊但還未實例化的監聽器
  • 實例化註冊表中的所有bean,創建bean的過程中會執行bean的初始化操作,會執行BeanPostProcessor、afterPropertiesSet、初始化方法等等
  • 調用finishRefresh,啟動所有bean,發佈ContextRefreshed事件

6.執行afterRefresh,調用實現瞭ApplicationRunner/CommandLineRunner接口的bean run方法

7.發佈ApplicationReadyEvent事件

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: