在 Spring Boot 中,初始化方法通常是在应用程序启动时被调用的,可以用来执行应用启动时的一些准备工作。以下是几种常见的初始化方法:
一、顺序
1. 图解
┌─────────────────────────────┐
│ Spring Boot启动 │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Spring Application │
│ Context 加载和注入 │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 依赖注入完成 │
│ (`@PostConstruct`) │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ `InitializingBean` │
│ 调用 `afterPropertiesSet()`│
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 初始化 `@Bean` │
│ (配置类中 `@Bean` 方法) │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ `CommandLineRunner` │
│ 和 `ApplicationRunner` │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 触发应用事件 │
│ (`ApplicationListener`) │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 应用启动完成 │
│ (`ApplicationReadyEvent`) │
└─────────────────────────────┘
2. 执行顺序过程
-
Spring Boot 启动 (SpringApplication.run())
这是应用启动的入口,它会初始化 Spring 上下文,加载所有 Bean 配置等。 -
依赖注入完成后 (@PostConstruct / InitializingBean)
@PostConstruct 在所有依赖注入完成后立即执行,用于执行一些初始化工作。
InitializingBean 的 afterPropertiesSet() 方法也在所有依赖注入完成后执行,通常用于进行一些逻辑初始化。 -
初始化 @Bean 方法
Spring 会在容器启动过程中调用配置类中的 @Bean 方法进行 Bean 初始化。这些方法通常用于返回一些 Spring 管理的 Bean。 -
CommandLineRunner 和 ApplicationRunner 执行
这些接口的 run() 方法会在 Spring Boot 完全初始化后执行,通常用于执行一些在应用启动完成后的操作。 -
ApplicationListener 监听器触发
ApplicationListener 可以监听 ApplicationReadyEvent 事件等,这个事件会在应用完全启动并准备就绪后触发。 -
应用启动完成 (ApplicationReadyEvent)
当应用启动并准备好后,ApplicationReadyEvent 会被触发。此时,应用就可以接受请求或执行其他操作了。
二、方法详解
1. @PostConstruct
注解
@PostConstruct
注解用于标注一个方法,表示在 Spring 完成所有依赖注入后,会调用该方法。这通常用于类初始化时执行的操作。
@Component
public class MyService {
@PostConstruct
public void init() {
System.out.println("Initializing MyService...");
}
}
2. CommandLineRunner
接口
CommandLineRunner
是 Spring Boot 提供的一个接口,它的 run
方法会在应用启动完成后执行。CommandLineRunner
接口允许开发者在应用启动时执行一些特定的逻辑。
@SpringBootApplication
public class MyApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("Application started with CommandLineRunner...");
}
}
3. ApplicationRunner
接口
ApplicationRunner
接口与 CommandLineRunner
类似,区别在于它提供了一个 ApplicationArguments
参数,可以获取启动时传入的命令行参数。
@SpringBootApplication
public class MyApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Application started with ApplicationRunner...");
System.out.println("Non-option arguments: " + args.getNonOptionArgs());
}
}
4. SpringApplication
类的 run()
方法
Spring Boot 的 SpringApplication
类的 run()
方法是应用启动的入口,它可以配置一些初始化行为,如设置应用的环境、启用配置文件等。
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setAdditionalProfiles("dev");
app.run(args);
}
5. @Configuration
配置类中的 @Bean
方法
在配置类中,通过 @Bean
注解定义的 Bean 方法,会在应用启动时被执行。
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
6. ApplicationListener
监听器
ApplicationListener
可以监听 Spring Boot 应用的启动事件,例如 ContextRefreshedEvent
或 ApplicationReadyEvent
,这些事件可以用于执行初始化逻辑。
@Component
public class AppStartupListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("Application is ready!");
}
}
7. @Bean
注解与 @PostConstruct
配合
如果你在 Spring 配置类中使用 @Bean
注解创建一个 Bean,并且需要在该 Bean 被创建后进行一些初始化操作,可以将 @PostConstruct
注解添加到 Bean 类中的初始化方法。
@Configuration
public class MyConfig {
@Bean
public MyService myService() {
return new MyService();
}
@PostConstruct
public void setup() {
System.out.println("Initializing configuration...");
}
}
8. InitializingBean
接口
InitializingBean
是 Spring 提供的一个接口,允许开发者在 Bean 被初始化之后执行特定的操作。这个接口与 @PostConstruct
注解有些类似,但 InitializingBean
是一个更传统的方式,适用于较早的 Spring 版本,而 @PostConstruct
是 Java EE 标准的一部分。InitializingBean
接口的主要方法是 afterPropertiesSet()
,它会在 Spring 容器完成依赖注入并且所有 Bean 属性都设置好之后执行。也就是说,afterPropertiesSet()
方法在 Bean 初始化时被调用,通常用于执行一些与 Bean 相关的初始化工作。
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class MyService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// 执行初始化操作
System.out.println("MyService has been initialized!");
}
}
执行顺序
在 Spring 中,InitializingBean
的 afterPropertiesSet()
方法的调用顺序如下:
- 依赖注入完成后:Spring 完成对所有 Bean 的依赖注入,确保所有的属性都被正确设置。
InitializingBean
的afterPropertiesSet()
被调用:Spring 会依次调用实现了InitializingBean
接口的 Bean 的afterPropertiesSet()
方法。@PostConstruct
注解方法被调用:如果@PostConstruct
方法存在,它将在afterPropertiesSet()
后调用。
InitializingBean
与 @PostConstruct
的区别
特性 | InitializingBean | @PostConstruct |
---|---|---|
接口/注解 | 接口 (InitializingBean ) | 注解 (@PostConstruct ) |
调用时机 | 在依赖注入完成之后调用 (afterPropertiesSet() ) | 在依赖注入完成之后调用(容器初始化后,通常早于 afterPropertiesSet() ) |
使用范围 | 需要实现 InitializingBean 接口 | 可以标注在任何一个方法上 |
适用场景 | 适用于老版本的 Spring 或者需要控制初始化逻辑的情况 | 适用于更简洁的场景,推荐用于标注简单初始化方法 |
与 @Bean 配合 | 可以与配置类中的 @Bean 配合,调用 afterPropertiesSet() | 一般情况下,@PostConstruct 用于实例化 Bean 时的初始化方法 |