Spring SmartLifecycle:如何精准控制Bean的生命周期

 更新时间:2025年03月26日 11:02:03   作者:catoop  
这篇文章主要介绍了Spring SmartLifecycle:如何精准控制Bean的生命周期问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、核心作用

SmartLifecycle 是 Spring 框架中用于 精确控制组件生命周期阶段 的高级接口,主要解决三类问题:

  1. 有序启停:控制多个组件启动/关闭顺序
  2. 阶段化处理:将初始化/销毁操作划分为不同阶段
  3. 上下文感知:获取应用上下文状态变化事件

二、典型应用场景

场景具体用途优势体现
连接池管理数据库/Redis连接池的预热和优雅关闭避免连接泄漏
线程池控制异步线程池的初始化与任务排空防止任务丢失
外部服务注册服务注册中心的上线通知与下线注销保证服务状态一致性
定时任务调度分布式任务调度器的启动与暂停精准控制任务执行周期
硬件设备控制IoT设备连接初始化与安全断开保障设备操作安全性

三、核心方法详解

public interface SmartLifecycle extends Lifecycle {
    
    // 关键方法1:启动组件(自动触发)
    void start();
    
    // 关键方法2:停止组件(带异步通知)
    default void stop(Runnable callback) {
        stop();
        callback.run();
    }
    
    // 关键方法3:相位控制(数值越小优先级越高)
    int getPhase();
    
    // 其他方法
    boolean isAutoStartup();
    boolean isRunning();
}

四、实战代码示例

基本案例:

@Component
public class DatabaseConnector implements SmartLifecycle {
    private volatile boolean running = false;
    private ConnectionPool pool;

    @Override
    public void start() {
        if (!running) {
            this.pool = initConnectionPool(); // 连接池预热
            running = true;
        }
    }

    @Override
    public void stop() {
        if (running) {
            pool.safeRelease(); // 安全释放连接
            running = false;
        }
    }

    @Override
    public int getPhase() {
        return Integer.MIN_VALUE + 1000; // 高优先级组件
    }
}

主动结束当前线程的处理案例:

@Slf4j
@Configuration
public class SensitiveWordsConfiguration implements SmartLifecycle {

    /**
     * lifeRunning
     */
    private volatile boolean lifeRunning = false;
    
    /**
     * 更新时间间隔
     */
    private static final long UPDATE_TIME_SECONDS = 10 * 60;
    
    /**
     * 是否终止线程
     */
    private volatile boolean threadStop = false;
    /**
     * taskExecutor
     */
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    /**
     * 当前线程任务
     */
    private Future<?> future;
    
    /**
     * 实现热更新,修改词典后自动加载
     */
    private void startScheduledUpdate() {
        while (!threadStop && !Thread.currentThread().isInterrupted()) {
            try {
                log.debug("SensitiveWordConfig#startScheduledUpdate start update...");
                
                //这里做业务处理
                //...
                
                TimeUnit.SECONDS.sleep(UPDATE_TIME_SECONDS);
            } catch (InterruptedException e) {
                log.info("SensitiveWordConfig#startScheduledUpdate interrupted: {}", e.getMessage());
                Thread.currentThread().interrupt();
                break;
            }
        }
    }

    @Override
    public void start() {
        // 启动定时更新任务线程
        this.future = taskExecutor.submit(this::startScheduledUpdate);
        lifeRunning = true;
    }

    @Override
    public void stop() {
        threadStop = true;
        // 主动终止当前线程的(否则会持续sleep直到线程池shutdownNow导致占用停止时间)
        this.future.cancel(true);
        lifeRunning = false;
    }

    @Override
    public boolean isRunning() {
        return lifeRunning;
    }

}

要特别注意的是:这个案例中使用了spring上下文中的 ThreadPoolTaskExecutor,所以不能使用 @PreDestroy 注解方法来进行回收处理,因为spring在关闭容器时会先对上下问中的线程池进行shutdown完成后,才会执行所有bean的destroy方法。

五、相位控制策略

通过 getPhase() 返回值控制执行顺序:

  • 启动顺序:相位值 从小到大 执行
  • 关闭顺序:相位值 从大到小 执行

六、与普通Lifecycle的区别

特性LifecycleSmartLifecycle
自动启动❌ 需手动触发✅ 支持自动启动
停止回调❌ 无✅ 带异步完成通知
执行顺序控制❌ 不支持✅ 相位值精确控制
上下文刷新集成❌ 有限支持✅ 深度集成上下文生命周期

七、注意事项

  1. 异常处理:在start()/stop()中必须捕获异常,避免阻断全局生命周期流程
  2. 线程安全:确保实现类方法的线程安全性
  3. 性能影响:避免在生命周期方法中执行耗时操作(>1秒的操作建议异步化)
  4. 容器兼容:与@PostConstruct/@PreDestroy注解配合使用时注意执行顺序。执行顺序 @PostConstruct > start() > stop() > @PreDestroy

通过合理使用 SmartLifecycle,可以实现 服务零中断重启资源按序回收 等高级功能,是构建企业级 Spring 应用的必备技能。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java:程序包com.xxx.xxx不存在报错万能解决办法

    java:程序包com.xxx.xxx不存在报错万能解决办法

    这篇文章主要给大家介绍了关于java:程序包com.xxx.xxx不存在报错万能解决办法,这个问题曾逼疯初学者的我,不过弄清楚原理后就很简单了,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Java多线程ForkJoinPool实例详解

    Java多线程ForkJoinPool实例详解

    这篇文章主要介绍了Java多线程ForkJoinPool实例详解,涉及forkjoin框架的相关内容,需要的朋友可以参考下。
    2017-09-09
  • APT 注解处理器实现 Lombok 常用注解功能详解

    APT 注解处理器实现 Lombok 常用注解功能详解

    这篇文章主要为大家介绍了使用APT 注解处理器实现 Lombok 常用注解功能详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • SpringBoot集成tomcat详解实现过程

    SpringBoot集成tomcat详解实现过程

    采用spring boot之后,一切变得如此简单,打包->java-jar->运维,只需要一个jar包便可以随意部署安装。这篇文章,将对 spring boot集成tomcat的源码进行分析,探索其内部的原理
    2023-02-02
  • java实现液晶数字字体显示当前时间

    java实现液晶数字字体显示当前时间

    这篇文章主要为大家详细介绍了java实现液晶数字字体显示当前时间,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • java泛型基本知识和通用方法

    java泛型基本知识和通用方法

    这篇文章主要介绍了java泛型基础知识及通用方法,从以下几个方面介绍一下java的泛型: 基础, 泛型关键字, 泛型方法, 泛型类和接口,感兴趣的可以了解一下
    2021-06-06
  • jedis的testWhileIdle用法源码解读

    jedis的testWhileIdle用法源码解读

    这篇文章主要为大家介绍了jedis的testWhileIdle用法源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • SpringBoot公共页面抽取方法实现过程介绍

    SpringBoot公共页面抽取方法实现过程介绍

    这篇文章主要介绍了SpringBoot抽取公共页面的方法实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • JAVA深入探究之Method的Invoke方法

    JAVA深入探究之Method的Invoke方法

    这篇文章主要给大家介绍了关于JAVA深入探究之Method的Invoke方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Idea中使用Git实现方式

    Idea中使用Git实现方式

    本文总结了在Idea中配置Git、创建远程仓库、弱化了暂存区等内容,详细介绍了复制仓库链接、创建本地仓库、提交、查看提交记录、推送、克隆、创建分支、切换、删除、创建、重命名分支等操作
    2026-05-05

最新评论