SpringBoot 啟動時執行某些操作的九種方式
前言
在真實項目開發過程中,我們經常會需要在程序啟動時執行一些特定的業務操作,比如系統預熱、系統初始化等。小編為大家介紹 9 種實現方式。
實現方案
一、ApplicationRunner
1. 執行時機
SpringBoot 應用完全啟動后。
2. 核心特點
實現 ApplicationRunner 接口,通過 ApplicationArguments 對象訪問參數,可以更方便地解析命令行參數(例如獲取--key=value形式的參數值)。
如果定義了多個Runner,可以使用 @Order 注解來控制他們的執行順序,數值越小優先級越高。
3. 代碼示例
@Component
@Order(1) // 執行順序,可選
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 這里寫你的啟動執行邏輯,例如初始化緩存
// args 可以訪問應用參數
}
}二、CommandLineRunner
1. 執行時機
SpringBoot 應用完全啟動后。
2. 核心特點
實現 CommandLineRunner 接口,通過 String... args 直接訪問命令行原始參數數組。
如果定義了多個Runner,可以使用 @Order 注解來控制他們的執行順序,數值越小優先級越高。
3. 代碼示例
@Component
@Order(2) // 執行順序,可選
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// 這里寫你的啟動執行邏輯
// args 可以訪問命令行原始參數
}
}三、@PostConstruct 注解
1. 執行時機
Bean 初始化時,在對象依賴注入完成后執行。
2. 核心特點
注解在方法上,使用簡單。
此時 Spring 容器可能還未完全初始化完畢,部分 Bean 可能尚未就緒,需注意可能的依賴問題。
3. 代碼示例
@Component
public class MyInitBean {
@Autowired
private SomeRepository repository; // 假設的倉庫類,用于數據訪問
@PostConstruct
public void init() {
// 例如,在項目啟動時從數據庫加載數據到靜態變量
List<SomeData> data = repository.findAll();
// ... 其他處理邏輯
}
}四、實現 InitializingBean 接口
1. 執行時機
Bean 的全部屬性被設置之后執行。
2. 核心特點
實現接口的 afterPropertiesSet 方法。
與 @PostConstruct 類似,都是 Bean 生命周期中的初始化方法。
3. 代碼示例
@Component
public class MyInitializingBean implements InitializingBean {
@Autowired
private SomeDependency dependency;
@Override
public void afterPropertiesSet() throws Exception {
// 確保屬性dependency注入后,再執行初始化
// 你的初始化邏輯
}
}五、實現 InitializingBean 接口
1. 執行時機
Bean 的全部屬性被設置之后執行。
2. 核心特點
實現接口的 afterPropertiesSet 方法。
與 @PostConstruct 類似,都是 Bean 生命周期中的初始化方法。
3. 代碼示例
@Component
public class MyInitializingBeanimplementsInitializingBean {
@Autowired
private SomeDependency dependency;
@Override
publicvoidafterPropertiesSet()throws Exception {
// 確保屬性dependency注入后,再執行初始化
// 你的初始化邏輯
}
}六、實現 BeanPostProcessor 接口
1. 執行時機
在 Bean 的初始化前后執行。
2. 核心特點
實現接口的 postProcessBeforeInitialization 與 postProcessAfterInitialization 方法。
這個接口會影響所有的 bean 初始化。
3. 代碼示例
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之前執行的邏輯
System.out.println("Before Initialization: " + beanName);
return bean; // 返回bean本身或一個新的bean實例(可選)
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之后執行的邏輯
System.out.println("After Initialization: " + beanName);
return bean; // 返回bean本身或一個新的bean實例(可選)
}
}七、實現 BeanFactoryPostProcessor 接口
1. 執行時機
在 Spring 容器初始化時執行,此時容器中所有的 Bean 定義已經加載完,但是 Bean 的實例還未創建。
2. 核心特點
實現接口的 postProcessBeanFactory 方法。
這個接口只會執行一次,執行時機早于 BeanPostProcessor 。
3. 代碼示例
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("******************** MyBeanFactoryPostProcessor#postProcessBeanFactory ****************");
System.out.println("******************** bean的數量:[{}] ****************", beanFactory.getBeanDefinitionCount());
BeanDefinition userBeanDef = beanFactory.getBeanDefinition("student");
// 修改bean definition屬性信息
}
}八、實現 ServletContextListener 接口
1. 執行時機
Web 應用啟動初期,在初始化任何過濾器或 Servlet 時或者銷毀 Web 容器時執行。
2. 核心特點
實現接口的 contextInitialized 和 contextDestroyed 方法。
適用于 Web 環境,監聽 Servlet 上下文。
3. 代碼示例
@Component
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 在這里寫Web應用啟動時的邏輯
// 例如,初始化一些Web應用級別的資源
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 在這里寫Web應用關閉時的清理邏輯
}
}九、static 靜態代碼塊
1. 執行時機
類被加載時執行。
2. 核心特點
僅僅是類被加載時,Bean 還未被創建。
3. 代碼示例
@Component
public class MyClass {
static {
System.out.println("執行靜態代碼塊")
}
}


























