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方法,最后清除所有单例对象。