在 Spring Boot 中,监听应用的启动和优雅停机(graceful shutdown)可以使用 ApplicationListener
监听 ApplicationReadyEvent
和 ApplicationFailedEvent
事件,同时通过 @PreDestroy
或 DisposableBean
处理关闭逻辑。下面是具体实现步骤:
可以监听 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 应用已启动,执行初始化逻辑...");
// 你可以在这里执行启动后的逻辑,比如加载缓存、预热资源等
}
}
Spring Boot 关闭时,可以使用以下几种方式执行清理逻辑:
@PreDestroy
注解DisposableBean
接口ApplicationListener
@PreDestroy
注解import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class ShutdownHook {
@PreDestroy
public void onShutdown() {
System.out.println("Spring Boot 应用即将关闭,执行清理逻辑...");
// 释放资源、关闭数据库连接、清理缓存等
}
}
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 应用正在关闭,释放资源...");
// 这里可以执行一些资源释放逻辑
}
}
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 应用已关闭,执行最终清理...");
// 关闭线程池、数据库连接等
}
}
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();
}
}
如果你的 Spring Boot 应用运行在 Docker 或 Kubernetes,你需要确保在 Dockerfile
或 Kubernetes
配置中使用 SIGTERM 信号触发优雅停机。
CMD ["java", "-jar", "your-app.jar"]
确保 ENTRYPOINT
不会被 SIGKILL
直接终止,否则优雅停机不会执行。
如果你运行在 Kubernetes,可以配置 preStop
钩子:
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
这样会给 Spring Boot 额外的时间来执行 @PreDestroy
或 DisposableBean
逻辑。
ApplicationListener
。@PreDestroy
、DisposableBean
或 ApplicationListener
。application.properties
中配置 server.shutdown=graceful
。SIGTERM
信号以触发优雅停机逻辑。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
@PreDestroy
Javadoc: https://jakarta.ee/specifications/platform/10/apidocs/jakarta/annotation/PreDestroyDisposableBean
Javadoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/DisposableBean.htmlSpring 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