Spring Lifecycle的使用小结

网友投稿 343 2022-07-31


目录前言Lifecycle自定义Lifecycle实现类测试SmartLifecycle自定义SmartLifecycle实现类多个实现类源码分析LifecycleProcessoronRefreshonClosestopdoStop

前言

小杰在前面的文章讲过可以使用 @PostConstruct、InitializingBean 、xml init、 @PreDestroy 、DisposableBean 、xml destroy来处理 Bean 的初始化和销毁,上述这些操作是属于 Bean 生命周期的。

那如果我想在容器本身的生命周期(比如容器启动、停止)上做一些工作怎么办呢?Spring 提供了以下接口。

Lifecycle

定义启动/停止生命周期方法的通用接口。

public interface Lifecycle {

/**

* 容器启动后调用

*/

void start();

/**

* 容器停止时调用

*/

void stop();

/**

* 检查此组件是否正在运行。

* 1. 只有该方法返回false时,start方法才会被执行。

* 2. 只有该方法返回true时,stop()方法才会被执行。

*/

boolean isRunning();

}

自定义Lifecycle实现类

@Component

public class CustomizeLifecycle implements Lifecycle {

private volatile boolean running = false;

@Override

public void start() {

running = true;

System.out.println("start ==== ");

}

@Override

public void stop() {

running = false;

System.out.println("stop ==== ");

}

@Override

public boolean isRunning() {

return running;

}

}

测试

@ComponentScan(basePackages = {"com.gongj.lifecycle"})

public class AppApplication {

public static void main(String[] args) {

AnnotationConfigApplicationContext context =

new AnnotationConfigApplicationContext(AppApplication.class);

context.start();

context.stop();

}

}

结果:

isRunning ====&http://gt; false

start ====>

isRunning ====> true

stop ====>

使用 Lifecycle这种方式,需要显示的调用容器的 start、stop方法。 显得笨重,所以我们使用另外一种方式 :SmartLifecycle。

SmartLifecycle

public interface SmartLifecycle extends Lifecycle, Phased {

int DEFAULT_PHASE = Integer.MAX_VALUE;

default boolean isAutoStartup() {

return true;

}

default void stop(Runnable callback) {

stop();

callback.run();

}

@Override

default int getPhase() {

return DEFAULT_PHASE;

}

}

看到的源码定义,SmartLifecycle除了继承Lifecycle之外,还继承了 Phased。并且新增了几个方法:

isAutoStartup:是否自动启动。为 treu,则自动调用start();为 false,则需要显示调用 start()。stop:当 isRunning 方法返回 true 时,该方法才会被调用。getPhase:来自于 Phased 接口,当容器中有多个实现了 SmartLifecycle的类,这个时候可以依据 getPhase方法返回值来决定start 方法、 stop方法的执行顺序。 start 方法执行顺序按照 getPhase方法返回值从小到大执行,而 stop方法则相反。比如: 启动时:1 比 3 先执行,-1 比 1 先执行,退出时:3 比 1 先退出,1 比 -1 先退出。

自定义SmartLifecycle实现类

@Component

public class CustomizeSmartLifecycle implements SmartLifecycle {

private volatile boolean running = false;

@Override

public void start() {

running = true;

System.out.println("CustomizeSmartLifecycle start()");

}

@Override

public void stop() {

System.out.println("CustomizeSmartLifecycle stop()");

running = false;

}

@Override

public boolean isRunning() {

System.out.println("CustomizeSmartLifecycle isRunning() ==== " + running);

return running;

}

@Override

public boolean isAutoStartup() {

return true;

}

@Override

public void stop(Runnable callback) {

System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");

callback.run();

}

@Override

public int getPhase() {

return 1;

}

}

将代码进行启动,控制台打印如下内容:

public static void main(String[] args) {

AnnotationConfigApplicationContext context =

new AnnotationConfigApplicationContext(AppApplication.class);

//context.start();

//context.stop();

}

结果:

CustomizeSmartLifecycle isRunning() ==== false

CustomizeSmartLifecycle start()

发现并没有执行 stop方法,这是因为容器问题。如果在Spring Boot项目会自动执行的,小伙伴可以试一试。

在本例中,还是需要显示调用 stop方法。

public static void main(String[] args) {

AnnotationConfigApplicationContext context =

new AnnotationConfigApplicationContext(Aphttp://pApplication.class);

//context.start();

context.stop();

}

结果:

CustomizeSmartLifecycle isRunning() ==== false

CustomizeSmartLifecycle start()

CustomizeSmartLifecycle isRunning() ==== true

CustomizeSmartLifecycle stop(Runnable callback)

发现执行了stop(Runnable callback),并没有执行 stop方法。这是因为当前类是 SmartLifecycle的子类,如果要执行 stop方法,需要在stop(Runnable callback)显示调用。

@Override

public void stop(Runnable callback) {

System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");

stop();

callback.run();

}

或者

@Override

public void stop(Runnable callback) {

SmartLifecycle.super.stop(callback);

}

启动结果如下:

CustomizeSmartLifecycle isRunning() ==== falseCustomizeSmartLifecycle start()CustomizeSmartLifecycle isRunning() ==== trueCustomizeSmartLifecycle stop(Runnable callback)CustomizeSmartLifecycle stop()

注意:在stop(Runnable callback)方法中不要忘记调用 callback.run()方法。否则DefaultLifecycleProcessor会认为这个SmartLifecycle没有stop完成,程序会等待一定时间,默认30秒后才会自动结束。

@Override

public void stop(Runnable callback) {

System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");

//stop();

//callback.run();

}

多个实现类

@Component

public class CustomizeSmartLifecycle2 implements SmartLifecycle {

private volatile boolean running = false;

@Override

public void start() {

running = true;

System.out.println("CustomizeSmartLifecycle2 start() =====>");

}

@Override

public void stop() {

System.out.println("CustomizeSmartLifecycle1 stop() =====>");

running = false;

}

@Override

public boolean isRunning() {

System.out.println("CustomizeSmartLifecycle2 isRunning() =====> " + running);

return running;

}

@Override

public boolean isAutoStartup() {

return true;

}

@Override

public void stop(Runnable callback) {

System.out.println("CustomizeSmartLifecycle2 stop(Runnable callback) =====>");

callback.run();

}

@Override

public int getPhase() {

return -1;

}

}

getPhase方法返回 -1。按照前面所说的结论,那就是 CustomizeSmartLifecycle2的start方法会先执行,然后 CustomizeSmartLifecycle2的stop方法最后执行。我们一起来看看执行结果吧!

public static void main(String[] args) {

AnnotationConfigApplicationContext context =

new AnnotationConfigApplicationContext(AppApplication.class);

//context.start();

context.stop();

}

执行结果:

CustomizeSmartLifecycle2 isRunning() =====> falseCustomizeSmartLifecycle2 start() =====>CustomizeSmartLifecycle isRunning() ==== falseCustomizeSmartLifecycle start()CustomizeSmartLifecycle isRunning() ==== trueCustomizeSmartLifecycle stop(Runnable callback)CustomizeSmartLifecycle2 isRunning() =====> trueCustomizeSmartLifecycle2 stop(Runnable callback) =====>

跟结论保持一致。

源码分析

基本的使用就到此结束啦!我们来结合源码分析分析吧!

我们来到 finishRefresh方法的 getLifecycleProcessor().onRefresh();方法。

protected void finishRefresh() {

// Clear context-level resource caches (such as ASM metadata from scanning).

clearResourceCaches();

// Initialize lifecycle processor for this context.

//为此上下文初始化生命周期处理器

initLifecycleProcessor();

// Propagate refresh to lifecycle processor first.

// 默认调用 DefaultLifecycleProcessor 的 onRefresh 方法

// 找出 Lifecycle Bean 执行 start 方法,默认情况下是没有Lifecycle Bean的,需要自己定义

getLifecycleProcessor().onRefresh();

// Publish the final event.

// 发布事件 ContextRefreshedEvent 是一个事件

publishEvent(new ContextRefreshedEvent(this));

// Participate in LiveBhttp://eansView MBean, if active.

LiveBeansView.registerApplicationContext(this);

}

getLifecycleProcessor()方法获得容器中的 LifecycleProcessor对象,默认就是 DefaultLifecycleProcessor。

LifecycleProcessor

public interface LifecycleProcessor extends Lifecycle {

/**

* Notification of context refresh, e.g. for auto-starting components.

* 上下文刷新的通知,例如 用于自动启动组件

*/

void onRefresh();

/**

* Notification of context close phase, e.g. for auto-stopping components.

* 上下文关闭的通知,例如 用于自动停止组件。

*/

void onClose();

}

接口中就定义的两个方法。onRefresh、onClose。

onRefresh

我们先来看一下 onRefresh方法的内部逻辑,分析它是如何自动调用 start方法的。

@Override

public void onRefresh() {

startBeans(true);

this.running = true;

}

private void startBeans(boolean autoStartupOnly) {

// 获取所有的Lifecycle Bean

Map lifecycleBeans = getLifecycleBeans();

// 将Lifecycle Bean 按阶段分组,阶段通过实现 Phased 接口得到

Map phases = new HashMap<>();

// 遍历所有Lifecycle Bean 按阶段值进行分组

lifecycleBeans.forEach((beanName, bean) -> {

// 当autoStartupOnly=false,显示调用 start()方法进行启动,会触发全部的Lifecycle;

// 当autoStartupOnly=true,调用容器的 refresh 方法启动,只会触发isAutoStartup方法返回true的SmartLifecycle

if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {

int phase = getPhase(bean);

LifecycleGroup group = phases.get(phase);

if (group == null) {

group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);

phases.put(phase, group);

}

group.add(beanName, bean);

}

});

if (!phases.isEmpty()) {

List keys = new ArrayList<>(phases.keySet());

Collections.sort(keys);

for (Integer key : keys) {

// 调用 Lifecycle 的 start 方法

phases.get(key).start();

}

}

}

这里注意一下 autoStartupOnly的值为 true。

autoStartupOnly=true,调用容器的 refresh 方法,由容器调用 onRefresh方法自动启动,只会触发 isAutoStartup方法返回 true 的SmartLifecycle。而 isAutoStartup属性,小杰在分析SmartLifecycle的时候已经讲过。autoStartupOnly=false,显示调用 start()方法进行启动,会触发全部的Lifecycle

@Override

public void start() {

getLifecycleProcessor().start();

publishEvent(new ContextStartedEvent(this));

}

//传入 false

@Override

public void start() {

startBeans(false);

this.running = true;

}

onClose

onClose在我没有找到调用点,但是 onClose内部会调用stopBeans()方法。我们直接分析stopBeans方法。

stopBeans方法跟 startBeans的逻辑大体差不多,然后调用 stop方法。

@Override

public void onClose() {

stopBeans();

this.running = false;

}

private void stopBeans() {

// 获取所有的Lifecycle Bean

Map lifecycleBeans = getLifecycleBeans();

Map phases = new HashMap<>();

lifecycleBeans.forEach((beanName, bean) -> {

// 获得 phase 的值

int shutdownPhase = getPhase(bean);

LifecycleGroup group = phases.get(shutdownPhase);

// 按阶段值进行分组

if (group == null) {

// this.timeoutPerShutdownPhase 就是等待时间

group = new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false);

phases.put(shutdownPhase, group);

}

group.add(beanName, bean);

});

if (!phases.isEmpty()) {

List keys = new ArrayList<>(phases.keySet());

keys.sort(Collections.reverseOrder());

for (Integer key : keys) {

//调用 stop 方法

phases.get(key).stop();

}

}

}

stop

创建一个 CountDownLatch对象,如果 count不为 0 ,则线程进行等待,默认等待 30 s。

public void stop() {

if(this.members.isEmpty()) {

return;

}

if(logger.isDebugEnabled()) {

logger.debug("Stopping beans in phase " + this.phase);

}

this.members.sort(Collections.reverseOrder());

// 创建 CountDownLatch 对象 ,count 为 smartMemberCount

// smartMemberCount 为 SmartLifecycle Bean的个数

CountDownLatch latch = new CountDownLatch(this.smartMemberCount);

Set < String > countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet < > ());

Set < String > lifecycleBeanNames = new HashSet < > (this.lifecycleBeans.keySet());

for(LifecycleGroupMember member: this.members) {

if(lifecycleBeanNames.contains(member.name)) quVFafvQSN{

//调用 dostop 方法

doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);

} else if(member.bean instanceof SmartLifecycle) {

// Already removed: must have been a dependent bean from another phase

//将count值减1

latch.countDown();

}

}

try {

//调用 await() 方法的线程会被挂起,等待一定的时间后,如果 count值还没有为 0 才继续执行

latch.await(this.timeout, TimeUnit.MILLISECONDS);

if(latch.getCount() > 0 && !countDownBeanNames.isEmpty(http://) && logger.isInfoEnabled()) {

logger.info("Failed to shut down " + countDownBeanNames.size() + " bean" + (countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " + this.phase + " within timeout of " + this.timeout + ": " + countDownBeanNames);

}

} catch(InterruptedException ex) {

Thread.currentThread().interrupt();

}

}

}

doStop

doStop 方法的逻辑很简单。区分是否是SmartLifecycle类型,如果是执行stop(Runnable callback)方法,反之执行 stop()方法。

private void doStop(Map lifecycleBeans, final String beanName,

final CountDownLatch latch, final Set countDownBeanNames) {

Lifecycle bean = lifecycleBeans.remove(beanName);

if (bean != null) {

String[] dependentBeans = getBeanFactory().getDependentBeans(beanName);

for (String dependentBean : dependentBeans) {

doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);

}

try {

// 判断 isRunning 的值

if (bean.isRunning()) {

// 如果是 SmartLifecycle 类型,则执行 stop(Runnable callback) 方法

if (bean instanceof SmartLifecycle) {

if (logger.isTraceEnabled()) {

logger.trace("Asking bean '" + beanName + "' of type [" +

bean.getClass().getName() + "] to stop");

}

countDownBeanNames.add(beanName);

// 这里就是为什么要调用 callback.run() 的原因

// 传入的是一个 lambad 表达式,所以需要调用callback.run(),才会执行 lambad 体

// 在lambad 体才会执行 latch.countDown()

((SmartLifecycle) bean).stop(() -> {

//将count值减1

latch.countDown();

countDownBeanNames.remove(beanName);

if (logger.isDebugEnabled()) {

logger.debug("Bean '" + beanName + "' completed its stop procedure");

}

});

}

else {

if (logger.isTraceEnabled()) {

logger.trace("Stopping bean '" + beanName + "' of type [" +

bean.getClass().getName() + "]");

}

// 否则执行 stop() 方法

bean.stop();

if (logger.isDebugEnabled()) {

logger.debug("Successfully stopped bean '" + beanName + "'");

}

}

}

else if (bean instanceof SmartLifecycle) {

// Don't wait for beans that aren't running...

latch.countDown();

}

}

catch (Throwable ex) {

if (logger.isWarnEnabled()) {

logger.warn("Failed to stop bean '" + beanName + "'", ex);

}

}

}

}

关于Lifecycle的使用与源码分析就到这啦!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring如何按业务模块输出日志到不同的文件详解
下一篇:java实现双人五子棋游戏(java编程五子棋游戏)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~