SpringBoot监听应用启动和优雅停机

SpringBoot监听应用启动和优雅停机

在 Spring Boot 中,监听应用的启动和优雅停机(graceful shutdown)可以使用 ApplicationListener 监听 ApplicationReadyEventApplicationFailedEvent 事件,同时通过 @PreDestroyDisposableBean 处理关闭逻辑。下面是具体实现步骤:


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 应用运行在 DockerKubernetes,你需要确保在 DockerfileKubernetes 配置中使用 SIGTERM 信号触发优雅停机。

Dockerfile

CMD ["java", "-jar", "your-app.jar"]

确保 ENTRYPOINT 不会被 SIGKILL 直接终止,否则优雅停机不会执行。

Kubernetes 配置

如果你运行在 Kubernetes,可以配置 preStop 钩子:

lifecycle:
  preStop:
    exec:
      command: ["/bin/sh", "-c", "sleep 10"]

这样会给 Spring Boot 额外的时间来执行 @PreDestroyDisposableBean 逻辑。


总结:

  • 监听启动事件 使用 ApplicationListener<ApplicationReadyEvent>
  • 监听优雅停机 可以使用 @PreDestroyDisposableBeanApplicationListener<ContextClosedEvent>
  • 启用优雅停机application.properties 中配置 server.shutdown=graceful
  • 在容器环境 需要正确处理 SIGTERM 信号以触发优雅停机逻辑。

参考链接

Spring Boot 启动和优雅停机

  1. 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

  2. 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

  3. Spring Context 关闭事件(ContextClosedEvent)
    https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/event/ContextClosedEvent.html

  4. @PreDestroy 和 DisposableBean

Spring Boot 与 Kubernetes / Docker 优雅停机

  1. Spring Boot 优雅停机 (server.shutdown=graceful)
    https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.web.server.shutdown

  2. Kubernetes PreStop Hook 介绍
    https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/

  3. Docker 容器优雅停机(Handling SIGTERM in Docker Containers)
    https://docs.docker.com/config/containers/runtime/#docker-init

在这里插入图片描述