Spring Boot启动后运行代码的方法

Spring Boot启动后运行代码的方法

技术背景

在开发Spring Boot应用时,有时需要在应用启动后执行一些特定的代码,例如监控目录变化、初始化数据等。然而,直接在启动时运行代码可能会遇到@Autowired服务未初始化的问题,因此需要找到合适的时机来执行这些代码。

实现步骤

1. 使用ApplicationReadyEvent

ApplicationReadyEvent会在应用刷新并处理完所有相关回调后触发,表明应用已准备好处理请求。可以通过@EventListener注解监听该事件。

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class StartupRunner {

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
}
}

2. 实现ApplicationListener<ApplicationReadyEvent>接口

创建一个类实现ApplicationListener<ApplicationReadyEvent>接口,并重写onApplicationEvent方法。

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
// 这里编写你的代码
}
}

3. 使用CommandLineRunnerApplicationRunner

CommandLineRunnerApplicationRunner是Spring Boot提供的接口,实现这些接口并重写run方法,Spring Boot会在应用启动过程的末尾执行这些方法。

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {

@Override
public void run(String... args) throws Exception {
System.out.println("Application started with command-line arguments: " + String.join(", ", args));
}
}

4. 使用@PostConstruct注解

在一个@Component类中使用@PostConstruct注解的方法会在Bean初始化完成后执行。

1
2
3
4
5
6
7
8
9
10
11
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class Monitor {

@PostConstruct
public void init() {
// 在这里启动监控
}
}

5. 使用SmartInitializingSingleton

在Spring 4.1及以上版本中,可以使用SmartInitializingSingleton,它会在所有单例Bean初始化完成后回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

@Bean
public SmartInitializingSingleton importProcessor() {
return () -> {
// 执行任务
};
}
}

核心代码

以下是几种方法的核心代码示例:

使用ApplicationReadyEvent

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class StartupExample {

@EventListener(ApplicationReadyEvent.class)
public void executeAfterStartup() {
System.out.println("执行启动后任务");
}
}

使用CommandLineRunner

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CommandLineExample implements CommandLineRunner {

@Override
public void run(String... args) throws Exception {
System.out.println("使用CommandLineRunner执行任务");
}
}

使用@PostConstruct

1
2
3
4
5
6
7
8
9
10
11
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class PostConstructExample {

@PostConstruct
public void init() {
System.out.println("使用@PostConstruct执行任务");
}
}

最佳实践

  • 如果代码需要在应用准备好处理请求后执行,推荐使用ApplicationReadyEvent
  • 如果需要处理命令行参数,可以使用CommandLineRunnerApplicationRunner
  • 如果代码是与Bean初始化相关的,可以使用@PostConstruct注解。
  • 如果需要在所有单例Bean初始化完成后执行代码,可以使用SmartInitializingSingleton

常见问题

  • @Autowired服务未初始化:使用ApplicationReadyEventCommandLineRunnerApplicationRunnerSmartInitializingSingleton可以确保@Autowired服务已初始化。
  • @PostConstruct方法执行过早@PostConstruct方法在Bean初始化时执行,可能会在应用整体准备好之前执行。如果需要在应用准备好后执行,不建议使用该注解。
  • ContextRefreshedEvent多次触发ContextRefreshedEvent可能会多次触发,需要在代码中添加判断逻辑,避免重复执行。

Spring Boot启动后运行代码的方法
https://119291.xyz/posts/2025-04-22.spring-boot-run-code-after-startup/
作者
ww
发布于
2025年4月22日
许可协议