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 应用的必备技能。


(END)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/972123.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图解JVM-1. JVM与Java体系结构

一、前言 在 Java 开发的广袤天地里&#xff0c;不少开发者都遭遇过令人头疼的状况。线上系统毫无征兆地卡死&#xff0c;陷入无法访问的僵局&#xff0c;甚至直接触发 OOM&#xff08;OutOfMemoryError&#xff0c;内存溢出错误&#xff09;&#xff1b;面对 JVM 的 GC&#…

深入浅出 Python Logging:从基础到进阶日志管理

在 Python 开发过程中&#xff0c;日志&#xff08;Logging&#xff09;是不可或缺的调试和监控工具。合理的日志管理不仅能帮助开发者快速定位问题&#xff0c;还能提供丰富的数据支持&#xff0c;让应用更具可观测性。本文将带你全面了解 Python logging 模块&#xff0c;涵盖…

设计模式15:中介者模式

系列总链接&#xff1a;《大话设计模式》学习记录_net 大话设计-CSDN博客 1.概述 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为设计模式&#xff0c;旨在通过一个中介对象来封装一系列对象之间的交互方式&#xff0c;从而减少这些对象间的直接依赖。在该模式…

爬取网站内容转为markdown 和 html(通常模式)

我们遇到一些自己喜欢内容&#xff0c;想保存下来&#xff0c;手动复制粘贴很麻烦&#xff0c;我们使用 python 来爬取这些内容。 一、代码 downlod.py import os import requests from bs4 import BeautifulSoup from urllib.parse import urljoin# 目标网页&#xff08;可…

【Linux】命令操作、打jar包、项目部署

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;Xshell下载 1&#xff1a;镜像设置 二&#xff1a;阿里云设置镜像Ubuntu 三&#xf…

Unity合批处理优化内存序列帧播放动画

Unity合批处理序列帧优化内存 介绍图片导入到Unity中的处理Unity中图片设置处理Unity中图片裁剪 创建序列帧动画总结 介绍 这里是针对Unity序列帧动画的优化内容&#xff0c;将多个图片合批处理然后为了降低Unity的内存占用&#xff0c;但是相对的质量也会稍微降低。可自行进行…

day4 多连联表慢查询sql查询优化

1.Explain分析sql语句出现的字段是什么意思 id: 查询的序列号&#xff0c;表示查询中 select 子句或操作表的顺序。 如果 id 相同&#xff0c;则执行顺序从上到下。 如果 id 不同&#xff0c;如果是子查询&#xff0c;id 的值会递增&#xff0c;id 值越大优先级越高&#xff0c…

基于豆瓣2025电影数据可视化分析系统的设计与实现

✔️本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示&#xff0c;构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据&#xff0c;我们提供了一个全面的电影信息平台&#xff0c;为用户提供深入了解电影产业趋势、影片评价与演员表现的工…

力扣高频sql 50题(基础版) :NULL, 表连接,子查询,case when和avg的结合

NULL的处理 nvl(字段,num) 和数字进行比较需要先使用nvl(字段,num)函数处理空值 思路: 没有被id 2 的客户推荐>> 过滤条件 referee_id !2 没有被id 2 的客户推荐>>被其他客户推荐, 但是也有可能没有被任何客户推荐>>NULL 考点: NULL是 不一个具体的数…

夜莺监控发布 v8.beta5 版本,优化 UI,新增接口认证方式便于鉴权

以防读者不了解夜莺&#xff0c;开头先做个介绍&#xff1a; 夜莺监控&#xff0c;英文名字 Nightingale&#xff0c;是一款侧重告警的监控类开源项目。类似 Grafana 的数据源集成方式&#xff0c;夜莺也是对接多种既有的数据源&#xff0c;不过 Grafana 侧重在可视化&#xff…

Python - 爬虫利器 - BeautifulSoup4常用 API

文章目录 前言BeautifulSoup4 简介主要特点&#xff1a;安装方式: 常用 API1. 创建 BeautifulSoup 对象2. 查找标签find(): 返回匹配的第一个元素find_all(): 返回所有匹配的元素列表select_one() & select(): CSS 选择器 3. 访问标签内容text 属性: 获取标签内纯文本get_t…

认识 ADB(Android Debug Bridge,Android SDK 中的一个工具)

一、ADB 概述 ADB&#xff0c;全称 Android Debug Bridge&#xff0c;是 Android SDK 中的一个工具 ADB 位于 Android SDK 下 platform-tools 目录中 ADB 起到调试桥的作用&#xff0c;ADB 可以让开发者通过 USB 连接安卓设备&#xff0c;并在电脑上执行各种命令&#xff0c;…

模拟解决哈希表冲突

目录 解决哈希表冲突原理&#xff1a; 模拟解决哈希表冲突代码&#xff1a; 负载因子&#xff1a; 动态扩容&#xff1a; 总结&#xff1a; HashMap和HashSet的总结&#xff1a; 解决哈希表冲突原理&#xff1a; 黑色代表一个数组&#xff0c;当 出现哈希冲突时&#xff0…

FPGA简介|结构、组成和应用

Field Programmable Gate Arrays&#xff08;FPGA&#xff0c;现场可编程逻辑门阵列&#xff09;&#xff0c;是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物&#xff0c; 是作为专用集成电路&#xff08;ASIC&#xff09;领域中的一种半定制电路而出现的&#xff0c…

【机器学习】超参数调优指南:交叉验证,网格搜索,混淆矩阵——基于鸢尾花与数字识别案例的深度解析

一、前言&#xff1a;为何要学交叉验证与网格搜索&#xff1f; 大家好&#xff01;在机器学习的道路上&#xff0c;我们经常面临一个难题&#xff1a;模型调参。比如在 KNN 算法中&#xff0c;选择多少个邻居&#xff08;n_neighbors&#xff09;直接影响预测效果。 • 蛮力猜…

UGUI RectTransform的SizeDelta属性

根据已知内容&#xff0c;SizeDelta offsetMax - offsetMin 1.锚点聚拢情况下 输出 那么此时SizeDelta就是UI元素的长宽大小 2. 锚点分散时 引用自此篇文章中的描述 揭秘&#xff01;anchoredPosition的几何意义&#xff01; SizeDelta offsetMax - offsetMin (rectMax…

51单片机入门_10_数码管动态显示(数字的使用;简单动态显示;指定值的数码管动态显示)

接上篇的数码管静态显示&#xff0c;以下是接上篇介绍到的动态显示的原理。 动态显示的特点是将所有位数码管的段选线并联在一起&#xff0c;由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选&#xff…

mybatis使用typeHandler实现类型转换

使用mybatis作为操作数据库的orm框架&#xff0c;操作基本数据类型时可以通过内置的类型处理器完成java数据类型和数据库类型的转换&#xff0c;但是对于扩展的数据类型要实现与数据库类型的转换就需要自定义类型转换器完成&#xff0c;比如某个实体类型存储到数据库&#xff0…

瑞萨RA-T系列芯片ADCGPT功能模块的配合使用

在马达或电源工程中&#xff0c;往往需要采集多路AD信号&#xff0c;且这些信号的优先级和采样时机不相同。本篇介绍在使用RA-T系列芯片建立马达或电源工程时&#xff0c;如何根据需求来设置主要功能模块ADC&GPT&#xff0c;包括采样通道打包和分组&#xff0c;GPT触发启动…

最新智能优化算法:牛优化( Ox Optimizer,OX)算法求解经典23个函数测试集,MATLAB代码

一、牛优化算法 牛优化&#xff08; OX Optimizer&#xff0c;OX&#xff09;算法由 AhmadK.AlHwaitat 与 andHussamN.Fakhouri于2024年提出&#xff0c;该算法的设计灵感来源于公牛的行为特性。公牛以其巨大的力量而闻名&#xff0c;能够承载沉重的负担并进行远距离运输。这种…