Spring拓展点之SmartLifecycle如何感知容器启动和关闭

Spring为我们提供了拓展点感知容器的启动与关闭,从而使我们可以在容器启动或者关闭之时进行定制的操作。Spring提供了Lifecycle上层接口,这个接口只有两个方法start和stop两个方法,但是这个接口并不是直接提供给开发者做拓展点,而是通过SmartLifecycle为拓展点。SmartLifecycle是Lifecycle子接口,既继承了Lifecycle也继承了Phased,这个接口Phased使SmartLifecycle可以分组通知。后续介绍下SmartLifecycle怎么使用,以及它的原理。

目录

使用案例

原理机制

start()执行时机-容器refresh时实例化所有的单例对象后执行拓展点start方法

stop()执行时机-容器close时优化执行拓展点的stop方法,再清除所有单例对象

总结


使用案例

1.定义一个实现SmartLifecycle的类:

java 复制代码
package com.cyl.lifecycle;

import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;

@Component
public class CylLifeCycle implements SmartLifecycle {
	private boolean isRunning;

	@Override
	public void start() {
		System.out.println("容器启动");
		isRunning = true;
	}

	@Override
	public void stop() {
		System.out.println("容器停止");
		isRunning = false;
	}

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

2.启动一个容器并关闭

java 复制代码
public static void main(String[] args) {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.register(AppConfig.class);
		context.refresh();
        System.out.println("-------------------");
        context.close();

}

输出结果

容器启动


容器停止

实现SmartLifecycle感知容器启动和关闭,要注意:

1.isRunning为false时,才能调用start();isRunning为true时,才能调用到stop();所以执行start()方法前要设置isRunning为false,执行完start()后设置为true。

2.实现SmartLifecycle的bean必须是单例;

分组特性一般都有多个实现SmartLifecycle类才用到,实现getPhase方法,同一个分组标记phase相同即可

java 复制代码
//分组2
@Component
public class CylLifeCycleSecond implements SmartLifecycle {
	private boolean isRunning;

	@Override
	public void start() {
		System.out.println(String.format("CylLifeCycleSecond分组%s容器启动",getPhase()));
		isRunning = true;
	}

	@Override
	public void stop() {
		System.out.println(String.format("CylLifeCycleSecond分组%s容器启动",getPhase()));
		isRunning = false;
	}

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

	@Override
	public int getPhase() {
		return 2;
	}
}


//分组1
@Component
public class CylLifeCycleFirst2 implements SmartLifecycle {
	private boolean isRunning;

	@Override
	public void start() {
		System.out.println(String.format("CylLifeCycleFirst2分组%s容器启动",getPhase()));
		isRunning = true;
	}

	@Override
	public void stop() {
		System.out.println(String.format("CylLifeCycleFirst2分组%s容器停止",getPhase()));
		isRunning = false;
	}

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

	@Override
	public int getPhase() {
		return 1;
	}
}

//分组1
@Component
public class CylLifeCycleFirst implements SmartLifecycle {
	private boolean isRunning;

	@Override
	public void start() {
		System.out.println(String.format("CylLifeCycleFirst分组%s容器启动",getPhase()));
		isRunning = true;
	}

	@Override
	public void stop() {
		System.out.println(String.format("CylLifeCycleFirst分组%s容器停止",getPhase()));
		isRunning = false;
	}

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

	@Override
	public int getPhase() {
		return 1;
	}
}

最后输出结果为:

CylLifeCycleFirst分组1容器启动

CylLifeCycleFirst2分组1容器启动

CylLifeCycleSecond分组2容器启动


CylLifeCycleSecond分组2容器启动

CylLifeCycleFirst分组1容器停止

CylLifeCycleFirst2分组1容器停止

原理机制

start()执行时机-容器refresh时实例化所有的单例对象后执行拓展点start方法

当容器执行refresh方法的最后一步finishRefresh时,会在这一步进行获取生命周期处理器

获取所有的生命周期处理器后先根据phase分组,分组后以组维度进行start

最终会执行start,在这里会判断bean.isRunning(),若是bean.isRunning()为false时才会执行start方法

stop()执行时机-容器close时优化执行拓展点的stop方法,再清除所有单例对象

onClose方法会调用到stopBeans,也会获取所有的生命周期处理器的phase进行分组,分组后以组维度进行stop

总结

Spring拓展点SmartLifecycle在容器启动阶段实例化所有单例对象后,获取所有实现SmartLifecycle的类,执行start方法;在容器关闭时,先获取所有实现SmartLifecycle的类,执行stop方法,最后清除所有单例对象。

相关推荐
杨杨杨大侠13 小时前
都能接模型、RAG 和 MCP,Java Agent 框架到底差在哪?
java
凤山老林14 小时前
Spring Boot 启动冲刺:耗时剖析、懒加载策略与事件驱动初始化优化
spring boot·后端·python
Thinker QAQ14 小时前
并发编程(九):BlockingQueue 与 Channel——语言层的原子性、可见性与有序性
java·python·go·并发编程·channel·blockingqueue·message passing
朱涛的自习室14 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
霸道流氓气质15 小时前
RAG 可观测性与生产监控实战:四层遥测模型、五大仪表盘与 OpenTelemetry 全链路追踪的 Java 生产级实现
java·人工智能·python
AOI小白新手上路15 小时前
autodl常用的tar 打包下载(数据集)命令手册:逐段拆解与套用模板
java·大数据·数据库
woniu_maggie17 小时前
SAP MDG主数据治理实战:从架构原理到项目实施全解析
后端
xiaoqiMikko17 小时前
Redis 实战(一):内存满了 —— 拒写、淘汰、被系统杀掉,以及删了 key 内存为什么不降(6.2.4 实测)
redis·后端
dishugj17 小时前
系统架构风险点、敏感点和权衡点的概念和区分
java·开发语言