有些Spring項目在啟動的時候需要預加載一些資源,有以下方式:
一、啟動前執行
1、Java類加載階段
①:static變量
在類加載的准備階段為static變量分配內存並設置類初始值(數據字段類型的默認值)
在類加載的初始化階段為static變量賦定義的值
②:static代碼塊
在類加載的初始化階段執行靜態代碼塊
2、監聽器
自定義監聽器實現ApplicationListener接口,監聽以下事件
容器開始啟動 | ApplicationStartingEvent |
二、啟動中執行
1、bean實例化階段
①:構造代碼塊
每次創建對象時執行一次,優先於構造方法執行
②:構造方法
每次創建對象時執行一次
2、Spring bean初始化階段
①:如果bean實現了BeanNameAware接口,Spring將調用setBeanName()方法將bean的ID傳遞入
②:如果bean實現了BeanFactoryAware接口,Spring將調用setBeanFactory()方法,將BeanFactory容器實例傳入
③:如果bean實現了ApplicationContextAware接口,Spring將調用setApplicationContext()方法,將bean所在的應用上下文的引用傳進來
④:@PostConstruct 標注的方法,在執行完構造器之后初始化對象時執行
⑤:afterPropertiesSet方法,若bean實現了InitializingBean接口,接着執行此初始化方法
⑥:initMethod,@Bean注解上自定義的初始化方法
3、Spring監聽器
自定義監聽器實現ApplicationListener接口,監聽以下事件
在環境(environment)准備完成,容器創建之前 | ApplicationEnvironmentPreparedEvent |
容器創建完成,並且准備完成,資源加載之前 | ApplicationContextInitializedEvent |
容器加載完成,刷新之前 | ApplicationPreparedEvent |
三、啟動后執行
1、Spring監聽器
自定義監聽器實現ApplicationListener接口,監聽以下事件
容器啟動完成 | ApplicationStartedEvent |
容器運行 | ApplicationReadyEvent |
容器啟動失敗 | ApplicationFailedEvent |
2、CommandLineRunner 和 ApplicationRunner
兩個接口都是在ApplicationStartedEvent事件之后執行 ,用於在Spring容器啟動完成后執行一些功能。
對應下圖,callRunners方法:
先執行 ApplicationRunner 后執行 CommandLineRunner
兩個接口都有一個run方法,區別在於run方法的入參不同
CommandLineRunner | void run(String... args) throws Exception; |
ApplicationRunner | void run(ApplicationArguments args) throws Exception; |
①:CommandLineRunner,接口,用於指示當一個bean被包含在一個SpringApplication中時應該運行它。可以在同一個應用程序上下文中定義多個CommandLineRunner bean,並且可以使用ordered接口或@Order注釋進行排序
②:ApplicationRunner,接口,用於指示當一個bean被包含在一個SpringApplication中時應該運行它。可以在同一個應用程序上下文中定義多個ApplicationRunner bean,並且可以使用ordered接口或@Order注釋進行排序
使用:自定義類實現CommandLineRunner或ApplicationRunner接口,在實現的run()方法里執行想要自動執行的代碼。
Order注解:
當有多個類實現了CommandLineRunner和ApplicationRunner接口時,可以通過在類上添加@Order注解來設定運行順序。
示例:
SpringApplicationStartedListener:
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 監聽當容器啟動后,做一些數據預熱工作
*/
@Component
public class SpringApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
// 加載數據到緩存 ...
}
}
CacheRunner:
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 容器啟動后預熱緩存
*/
@Component
public class CacheRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 預熱緩存...
}
}
END.