Spring Lifecycle的使用小结
前言
小杰在前面的文章讲过可以使用 @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 ====> 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(AppApplication.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() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle 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() =====> false
CustomizeSmartLifecycle2 start() =====>
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
CustomizeSmartLifecycle2 isRunning() =====> true
CustomizeSmartLifecycle2 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 LiveBeansView 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<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); // 将Lifecycle Bean 按阶段分组,阶段通过实现 Phased 接口得到 Map<Integer, LifecycleGroup> 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<Integer> 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<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> 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<Integer> 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)) { //调用 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() && 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<String, ? extends Lifecycle> lifecycleBeans, final String beanName, final CountDownLatch latch, final Set<String> 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
的使用与源码分析就到这啦!
到此这篇关于Spring Lifecycle的使用的文章就介绍到这了,更多相关Spring Lifecycle使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot中@RestControllerAdvice @ExceptionHandler异常统一处
这篇文章主要介绍了SpringBoot中@RestControllerAdvice @ExceptionHandler异常统一处理类失效原因,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-01-01Java监听器ActionListener与MouseListener的执行顺序说明
这篇文章主要介绍了Java监听器ActionListener与MouseListener的执行顺序说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-12-12详解Maven项目Dependencies常见报错及解决方案
这篇文章主要介绍了详解Maven项目Dependencies常见报错及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-11-11springcloud gateway自定义断言规则详解,以后缀结尾进行路由
这篇文章主要介绍了springcloud gateway自定义断言规则详解,以后缀结尾进行路由,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-10-10intellij idea设置统一JavaDoc模板的方法详解
这篇文章主要介绍了intellij idea设置统一JavaDoc模板的方法详解,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2021-04-04
最新评论