SpringBoot监听应用启动和优雅停机
在 Spring Boot 中,监听应用的启动和优雅停机(graceful shutdown)可以使用 ApplicationListener
监听 ApplicationReadyEvent
和 ApplicationFailedEvent
事件,同时通过 @PreDestroy
或 DisposableBean
处理关闭逻辑。下面是具体实现步骤:
1. 监听 Spring Boot 启动
可以监听 ApplicationReadyEvent
事件,当 Spring Boot 应用成功启动后,执行自定义逻辑。
代码示例:
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationStartupListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("Spring Boot 应用已启动,执行初始化逻辑...");
// 你可以在这里执行启动后的逻辑,比如加载缓存、预热资源等
}
}
2. 监听 Spring Boot 关闭(优雅停机)
Spring Boot 关闭时,可以使用以下几种方式执行清理逻辑:
@PreDestroy
注解- 实现
DisposableBean
接口 ApplicationListener<ContextClosedEvent>
方式 1:使用 @PreDestroy
注解
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class ShutdownHook {
@PreDestroy
public void onShutdown() {
System.out.println("Spring Boot 应用即将关闭,执行清理逻辑...");
// 释放资源、关闭数据库连接、清理缓存等
}
}
方式 2:实现 DisposableBean
接口
import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;
@Component
public class GracefulShutdownHandler implements DisposableBean {
@Override
public void destroy() {
System.out.println("Spring Boot 应用正在关闭,释放资源...");
// 这里可以执行一些资源释放逻辑
}
}
方式 3:监听 ContextClosedEvent
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;
@Component
public class ApplicationShutdownListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
System.out.println("Spring Boot 应用已关闭,执行最终清理...");
// 关闭线程池、数据库连接等
}
}
3. 配合 shutdown hook
进行资源管理(可选)
Spring Boot 2.3+ 版本默认支持优雅停机(graceful shutdown),可以使用 ShutdownHook
进行资源管理。
步骤:
在 application.properties
启用优雅停机:
server.shutdown=graceful
然后创建一个 ShutdownHook
来管理资源:
import org.springframework.stereotype.Component;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
public class GracefulShutdownService {
private final ExecutorService executorService = Executors.newFixedThreadPool(2);
public void executeTask(Runnable task) {
executorService.submit(task);
}
@PreDestroy
public void cleanup() {
System.out.println("应用关闭中,等待任务完成...");
executorService.shutdown();
}
}
4. 在 Kubernetes 或 Docker 中确保优雅停机
如果你的 Spring Boot 应用运行在 Docker 或 Kubernetes,你需要确保在 Dockerfile
或 Kubernetes
配置中使用 SIGTERM 信号触发优雅停机。
Dockerfile
CMD ["java", "-jar", "your-app.jar"]
确保 ENTRYPOINT
不会被 SIGKILL
直接终止,否则优雅停机不会执行。
Kubernetes 配置
如果你运行在 Kubernetes,可以配置 preStop
钩子:
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
这样会给 Spring Boot 额外的时间来执行 @PreDestroy
或 DisposableBean
逻辑。
总结:
- 监听启动事件 使用
ApplicationListener<ApplicationReadyEvent>
。 - 监听优雅停机 可以使用
@PreDestroy
、DisposableBean
或ApplicationListener<ContextClosedEvent>
。 - 启用优雅停机 在
application.properties
中配置server.shutdown=graceful
。 - 在容器环境 需要正确处理
SIGTERM
信号以触发优雅停机逻辑。
参考链接
Spring Boot 启动和优雅停机
-
Spring Boot 事件监听(Application Events and Listeners)
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.spring-application.application-events-and-listeners -
Spring Boot 生命周期(Application Lifecycle and Shutdown Hooks)
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.spring-application.application-lifecycle-and-shutdown -
Spring Context 关闭事件(ContextClosedEvent)
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/event/ContextClosedEvent.html -
@PreDestroy 和 DisposableBean
Spring Boot 与 Kubernetes / Docker 优雅停机
-
Spring Boot 优雅停机 (
server.shutdown=graceful
)
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.web.server.shutdown -
Kubernetes PreStop Hook 介绍
https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ -
Docker 容器优雅停机(Handling SIGTERM in Docker Containers)
https://docs.docker.com/config/containers/runtime/#docker-init