Spring Boot中的8种初始化方法
在 Spring Boot 项目中,初始化操作是不可或缺的一部分。它们确保应用在启动时进行必要的配置、数据加载、资源初始化等工作。本文将深入探讨 Spring Boot 中常见的几种初始化操作方式,并对它们的执行顺序进行比较,帮助你选择最适合你项目的方案。
1. @PostConstruct
@PostConstruct 是 Java 的标准注解,它标记的方法会在依赖注入完成后立即被调用。
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
@Component
public class MyPostConstructBean {
@PostConstruct
public void init() {
System.out.println("PostConstruct执行");
}
}
特点:
- 适用于简单的初始化逻辑。
- 依赖注入完成后立即执行。
- 执行顺序较早。
2. InitializingBean 接口
实现 InitializingBean 接口并重写 afterPropertiesSet 方法,也是进行初始化操作的一种方式。
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean接口的afterProperiesSet执行");
}
}
特点:
- 比 @PostConstruct 更具可读性,适合复杂的初始化逻辑。
- 依赖注入完成后调用。
- 执行顺序与 @PostConstruct 类似,但稍晚。
3. @Bean 注解中的 initMethod
使用 @Configuration 配置类中的 @Bean 注解时,可以指定 initMethod 属性来定义初始化方法。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean(initMethod = "init")
public MyBean myBean() {
return new MyBean();
}
}
class MyBean {
public void init() {
System.out.println("@Bean的initMethod方法执行");
}
}
特点:
- 明确指定初始化方法。
- 更易于配置和管理初始化逻辑。
- 执行顺序在 @PostConstruct 和 InitializingBean 之后。
4. CommandLineRunner 接口
实现 CommandLineRunner 接口的组件会在 Spring Boot 应用启动完成后执行。
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("CommandLineRunner接口的run方法执行");
}
}
特点:
- 用于需要在应用完全启动后执行的初始化逻辑。
- 接受应用启动参数。
- 执行顺序在所有 Spring 组件初始化完成之后。
5. ApplicationRunner 接口
与 CommandLineRunner 类似,但提供了更高级的参数解析能力。
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
System.out.println("ApplicationRunner接口的run方法执行");
}
}
特点:
- 与 CommandLineRunner 相似,但具有更强的参数处理能力。
- 用于需要在应用完全启动后执行的初始化逻辑。
- 执行顺序与 CommandLineRunner 相同。
6. @EventListener事件监听
使用 @EventListener 注解,可以在应用启动的某个生命周期阶段执行初始化逻辑。比如监听 ContextRefreshedEvent 事件,这个事件会在 Spring 上下文初始化或刷新时发布。
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyContextRefreshedListener {
@EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
System.out.println("@EventListener监听ContextRefreshedEvent事件执行");
}
}
特点:
- 适用于需要在特定生命周期事件发生时执行的初始化逻辑。
- 可以监听各种生命周期事件,如 ContextRefreshedEvent、ContextClosedEvent 等。
7. SmartInitializingSingleton
实现 SmartInitializingSingleton 接口的 afterSingletonsInstantiated 方法,可以在所有单例 bean 都初始化完成后执行。
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行");
}
}
特点:
- 在所有单例 bean 初始化完成后执行。
- 适用于需要确保所有单例 bean 都已准备好时执行的初始化逻辑。
8. ApplicationListener
实现 ApplicationListener 接口,可以监听特定的 Spring 事件,如 ApplicationReadyEvent,这个事件在 Spring 应用完全启动后触发。
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationReadyListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行");
}
}
特点:
- 用于在应用完全启动后执行逻辑。
- 可以监听各种 Spring 事件,提供灵活的初始化时机。
执行顺序综合比较
下面通过代码测试来看看它们的执行顺序,先准备以下代码,通过@Bean创建ExampleBean,在ExampleBean中放入了各种初始化的方式。
@Configuration
public class ExampleConfig {
@Bean(initMethod = "initMethod")
public ExampleBean initExampleBean() {
return new ExampleBean();
}
}
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import javax.annotation.PostConstruct;
public class ExampleBean implements InitializingBean, CommandLineRunner, ApplicationRunner, SmartInitializingSingleton,
ApplicationListener<ApplicationReadyEvent> {
public ExampleBean() {
System.out.println("构造器执行");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean接口的afterProperiesSet执行");
}
@Override
public void run(String... args) {
System.out.println("CommandLineRunner接口的run方法执行");
}
@Override
public void run(ApplicationArguments args) {
System.out.println("ApplicationRunner接口的run方法执行");
}
@Override
public void afterSingletonsInstantiated() {
System.out.println("SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行");
}
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行");
}
@PostConstruct
public void postConstruct() {
System.out.println("PostConstruct执行");
}
public void initMethod() {
System.out.println("@Bean标的initMethod方法执行");
}
@EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
System.out.println("@EventListener监听ContextRefreshedEvent事件执行");
}
}
启动项目运行之后,下面是控制台日志输出结果:
构造器执行
PostConstruct执行
InitializingBean接口的afterProperiesSet执行
@Bean标的initMethod方法执行
SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行
@EventListener监听ContextRefreshedEvent事件执行
...
com.pujiho.practice.MyApplication : Started LoginApplication in 2.587 seconds (JVM running for 6.749)
...
ApplicationRunner接口的run方法执行
CommandLineRunner接口的run方法执行
监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行
所以,综合所有提到的初始化方式,以下是它们的大致执行顺序:
- @PostConstruct
- InitializingBean.afterPropertiesSet
- @Bean 的 initMethod
- SmartInitializingSingleton.afterSingletonsInstantiated
- @EventListener (如 ContextRefreshedEvent)
- ApplicationRunner.run
- CommandLineRunner.run
- ApplicationListener (如 ApplicationReadyEvent)
结语
在 Spring Boot 中,选择合适的初始化方式取决于你的具体需求和初始化逻辑的复杂程度。@PostConstruct 和 InitializingBean 适合早期的、简单的初始化操作,而 CommandLineRunner 和 ApplicationRunner 更适合在应用完全启动后执行的复杂逻辑。了解这些初始化方式的执行顺序和特点,能够帮助你在项目中做出最佳选择,确保应用的平稳启动。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异