什么是SmartLifecycle生命周期接口接口
Spring Boot 的 SmartLifecycle 是 Spring 框架中的一种生命周期接口,它扩展了 Lifecycle 接口。Lifecycle 接口允许你控制一个组件的生命周期,例如启动和停止。而 SmartLifecycle 接口则在此基础上提供了更智能的控制,它能够处理多个 SmartLifecycle 实例的自动排序和依赖管理。
为什么要用SmartLifecycle
在SpringBoot的应用中,我们通常会利用@PostConstruct和@PreDestroy注解,在Bean初始化或销毁时执行一些操作,这些操作都处于Bean声明周期的层面。
然而,在某些情况下,我们可能会遇到一些遗漏的场景,比如希望在容器本身的生命周期事件(如容器启动、停止)上执行一些操作,一个典型的例子就是在Spring Boot中启动内嵌的Web容器。这时候,该如何处理呢?
这就是我们需要利用Spring提供的另一个接口Lifecycle。接下来,我们将介绍一下Lifecycle接口以及比它更智能的SmartLifecycle。
接口Lifecycle
在SpringBoot应用中如果没有调用AbstractApplicationContext#start方法,只是实现了Lifecycle接口,是不会执行Lifecycle接口中的启动方法和isRunning方法的。但在应用退出时会执行Lifecycle#isRunning方法判断该Lifecycle是否已经启动,如果返回true则调用Lifecycle#stop()停止方法。

如果使用者没有显式的调用容器的start()和stop()方法,Lifecycle的接口方法不会被执行。
而在一般的项目中,我们很少这样显式的去调用,所以就需要一个更“聪明”的类来处理,这就是SmartLifecycle。
接口SmartLifecycle
Spring Boot 的 SmartLifecycle 是 Spring 框架中的一种生命周期接口,它扩展了 Lifecycle 接口。Lifecycle 接口允许你控制一个组件的生命周期,例如启动和停止。而 SmartLifecycle 接口则在此基础上提供了更智能的控制,它能够处理多个 SmartLifecycle 实例的自动排序和依赖管理。

SmartLifecycle 接口关键方法
isAutoStartup():返回一个布尔值,指示这个生命周期组件是否应该在 Spring 容器启动时自动启动。getPhase():返回一个整数,表示这个生命周期组件的启动顺序。数值越小,组件启动的越早。start():启动这个生命周期组件。stop():停止这个生命周期组件。stop(Runnable callback):停止生命周期组件,并在停止后执行提供的回调。

SmartLifecycle 的智能之处在于,它允许多个组件根据 getPhase() 方法返回的值自动排序,确保它们按照正确的顺序启动和停止。这对于需要依赖其他组件启动后再启动的场景非常有用。
例如,在 Spring Boot 应用中,你可能会有一些组件需要在数据库连接建立之后才能启动,或者需要在某些服务注册到 Eureka 服务器之后才能启动。通过使用 SmartLifecycle,你可以确保这些组件在依赖条件满足后按正确的顺序启动。
如何使用getPhase()
例子1
import org.springframework.stereotype.Component;
import org.springframework.context.SmartLifecycle;
import org.springframework.beans.factory.annotation.Autowired;
//by https://zhengkai.blog.csdn.net/
@Component
public class MySmartLifecycleComponent implements SmartLifecycle {
private final SomeDependency someDependency; // 假设这是你的组件依赖
private volatile boolean running = false;
public MySmartLifecycleComponent(SomeDependency someDependency) {
this.someDependency = someDependency;
}
@Override
public boolean isAutoStartup() {
// 返回true表示在Spring容器启动时自动启动
return true;
}
@Override
public void start() {
// 启动逻辑
if (!this.running) {
// 这里可以添加启动前的检查,比如依赖是否已经启动
// 例如:if (someDependency.isReady()) {
System.out.println("MySmartLifecycleComponent is starting.");
// 启动组件
this.running = true;
// }
}
}
@Override
public void stop() {
// 停止逻辑
if (this.running) {
System.out.println("MySmartLifecycleComponent is stopping.");
this.running = false;
// 执行停止操作
}
}
@Override
public int getPhase() {
// 返回启动顺序,数值越小,启动越早
return 0;
}
// SmartLifecycle接口的stop(Runnable callback)方法可以根据需要重写
@Override
public void stop(Runnable callback) {
stop(); // 首先调用普通的停止方法
if (callback != null) {
callback.run(); // 停止后执行回调
}
}
}
例子2
import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;
@Component
public class MySmartLifecycle implements SmartLifecycle {
private volatile boolean running = false;
/**
* 如果该`Lifecycle`类所在的上下文在调用`refresh`时,希望能够自己自动进行回调,则返回`true`,
* false的值表明组件打算通过显式的start()调用来启动,类似于普通的Lifecycle实现。
* 默认就是true,所以可以不用重写此方法。
*/
// @Override
// public boolean isAutoStartup() {
// return true;
// }
/**
* 1. 主要在该方法中启动任务或者其他异步服务,比如开启MQ接收消息<br/>
* 2. 当上下文被刷新(所有对象已被实例化和初始化之后)时,将调用该方法,
* 默认生命周期处理器将检查每个SmartLifecycle对象的isAutoStartup()方法返回的布尔值。
* 如果为“true”,则该方法会被调用,而不是等待显式调用自己的start()方法。
*/
@Override
public void start() {
System.out.println("MySmartLifecycle容器启动完成 ...");
running = true;
}
/**
* SmartLifecycle子类的才有的方法,当isRunning方法返回true时,该方法才会被调用。
* 很多框架中的源码中,都会把真正逻辑写在stop()方法内。
* 比如quartz和Redis的spring支持包。
*/
@Override
public void stop(Runnable callback) {
System.out.println("MySmartLifecycle容器停止,执行回调函数");
stop();
// 如果你让isRunning返回true,需要执行stop这个方法,那么就不要忘记调用callback.run()。
// 否则在程序退出时,Spring的DefaultLifecycleProcessor会认为这个MySmartLifecycle没有stop完成,程序会一直卡着结束不了,等待一定时间(默认超时时间30秒)后才会自动结束。
callback.run();
}
/**
* 接口Lifecycle子类的方法,只有非SmartLifecycle的子类才会执行该方法。<br/>
* 1. 该方法只对直接实现接口Lifecycle的类才起作用,对实现SmartLifecycle接口的类无效。<br/>
* 2. 方法stop()和方法stop(Runnable callback)的区别只在于,后者是SmartLifecycle子类的专属。
*/
@Override
public void stop() {
System.out.println("MySmartLifecycle容器停止 ...");
running = false;
}
/**
* 1. 只有该方法返回false时,start方法才会被执行。<br/>
* 2. 只有该方法返回true时,stop(Runnable callback)或stop()方法才会被执行。
*/
@Override
public boolean isRunning() {
System.out.println("MySmartLifecycle检查运行状态 ...");
return running;
}
/**
* 如果有多个实现接口SmartLifecycle的类,则这些类的start的执行顺序按getPhase方法返回值从小到大执行。<br/>
* 例如:1比2先执行,-1比0先执行。stop方法的执行顺序则相反,getPhase返回值较大类的stop方法先被调用,小的后被调用。
*
*/
@Override
public int getPhase() {
return 0;
}
}
启动的日志打印:
MySmartLifecycle检查运行状态 ...
MySmartLifecycle容器启动完成 ...
关闭的日志打印:
MySmartLifecycle检查运行状态 ...
MySmartLifecycle容器停止,执行回调函数
MySmartLifecycle容器停止 ...
SmartLifecycle使用场景
(1)异步初始化或销毁操作: SmartLifecycle接口允许在容器启动或关闭过程中执行异步操作。这对于需要在应用程序启动或关闭时执行长时间运行的任务或资源清理操作非常有用。
(2)有序启动和关闭: SmartLifecycle可以指定组件的启动和关闭顺序,确保在启动或关闭过程中其他组件已经准备好或者已经完成。当你的组件在启动的时候,有依赖关系的话,那么就可以SmartLifecycle来进行控制组件的启动顺序。
(3)动态决定启动和关闭: SmartLifecycle接口中的方法能够让组件动态地决定何时启动或关闭。这使得在特定条件满足时才启动或关闭组件成为可能,从而提高了系统的灵活性和可控性。
(4)状态管理: SmartLifecycle接口提供了方法来查询组件的当前状态,例如是否已经启动或停止。这对于在应用程序的其他部分中根据组件状态做出决策或执行特定的逻辑非常有用。
(5)资源监控器的启动和停止: 如果应用程序中存在资源监控器,可以使用SmartLifecycle接口来启动和停止这些监控器。在应用程序启动时,监控器可以开始监控资源的使用情况。在应用程序关闭时,可以停止监控器并释放资源。
以下是一些具体的SmartLifecycle接口的应用场景:
(1)数据库连接池的管理: 在应用程序启动时,可以利用SmartLifecycle接口来初始化数据库连接池。在应用程序关闭时,可以利用SmartLifecycle接口来优雅地关闭数据库连接池,确保所有数据库连接都已释放。
(2)缓存的初始化和销毁: 在应用程序启动时,可以使用SmartLifecycle接口来初始化缓存并加载数据。在应用程序关闭时,可以使用SmartLifecycle接口来优雅地销毁缓存并释放资源。
(3)定时任务的管理: 如果应用程序中存在定时任务,可以使用SmartLifecycle接口来启动和关闭这些定时任务。在应用程序启动时,定时任务可以注册并开始执行。在应用程序关闭时,可以优雅地停止定时任务的执行。
SmartLifeCycle例子
FeignClientFactoryBean

NacosWatch
1542

被折叠的 条评论
为什么被折叠?



