• Spring优雅关闭之:ShutDownHook


    转载自:https://blog.csdn.net/qq_26323323/article/details/89814410

    2020/02/26重新编辑一下

    前面介绍ShutDownHook的基本使用方法,但是没有清楚的表述如何在SpringBoot中运用,这里我们来补充一下:

    查阅SpringBoot官方文档有这么一段描述:

    1.10. Application Exit

    Each SpringApplication registers a shutdown hook with the JVM to ensure that the ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface or the @PreDestroy annotation) can be used.

    官方介绍了两种方法:

    1. 直接实现DisposableBean接口,实现destroy方法即可

    @Slf4j
    @Component
    public class CustomShutdownHook implements DisposableBean {
    
        @Override
        public void destroy() throws Exception {
        }
    
    }

    2. 在方法上使用@PreDestroy注解,类似@PostConstruct注解使用方法。

      

    1. Runtime.addShutDownHook(Thread hook)

    // 创建HookTest,我们通过main方法来模拟应用程序
    public class HookTest {
     
        public static void main(String[] args) {
     
            // 添加hook thread,重写其run方法
            Runtime.getRuntime().addShutdownHook(new Thread(){
                @Override
                public void run() {
                    System.out.println("this is hook demo...");
                    // TODO
                }
            });
     
            int i = 0;
            // 这里会报错,我们验证写是否会执行hook thread
            int j = 10/i;
            System.out.println("j" + j);
        }
    }

     

    2. Runtime.addShutDownHook(Thread hook)应用场景

        * 程序正常退出

        * 使用System.exit()

        * 终端使用Ctrl+C触发的中断

        * 系统关闭

        * OutofMemory宕机

        * 使用Kill pid杀死进程(使用kill -9是不会被调用的)

    3. Spring如何添加钩子函数

    // 通过这种方式来添加钩子函数
    ApplicationContext.registerShutdownHook();
     
    // 通过源码可以看到,
    @Override
    public void registerShutdownHook() {
        if (this.shutdownHook == null) {
            // No shutdown hook registered yet.
            this.shutdownHook = new Thread() {
                @Override
                public void run() {
                    synchronized (startupShutdownMonitor) {
                        doClose();
                    }
                }
            };
            // 也是通过这种方式来添加
            Runtime.getRuntime().addShutdownHook(this.shutdownHook);
        }
    }
     
    // 重点是这个doClose()方法
     
    protected void doClose() {
        // Check whether an actual close attempt is necessary...
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (logger.isInfoEnabled()) {
                logger.info("Closing " + this);
            }
     
            LiveBeansView.unregisterApplicationContext(this);
     
            try {
                // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }
     
            // Stop all Lifecycle beans, to avoid delays during individual destruction.
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }
     
            // Destroy all cached singletons in the context's BeanFactory.
            destroyBeans();
     
            // Close the state of this context itself.
            closeBeanFactory();
     
            // Let subclasses do some final clean-up if they wish...
            onClose();
     
            // Switch to inactive.
            this.active.set(false);
        }
    }

    可以看到:doClose()方法会执行bean的destroy(),也会执行SmartLifeCycle的stop()方法,我们就可以通过重写这些方法来实现对象的关闭,生命周期的管理,实现平滑shutdown

  • 相关阅读:
    【区块链整理】四、区块链数据结构
    【区块链整理】三、以太坊挖矿算法 ETHASH
    【区块链整理】二、比特币交易脚本
    【区块链整理】一、概念
    FISCO BCOS CRUD 功能和 CNS 合约命名服务杂记
    前台静态资源打包ios
    叹而立之年,忆往昔旧事
    基于Bootstrap table组件实现多层表头配置
    js或jQuery获取当前屏幕的各种高度
    echarts图表基础配置
  • 原文地址:https://www.cnblogs.com/changxy-codest/p/11944401.html
Copyright © 2020-2023  润新知