Spring优雅关闭之:ShutDownHook

转载自:http://www.javashuo.com/article/p-wechjgnv-bg.htmlide

 

2020/02/26从新编辑一下函数

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

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

 

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..net

 

官方介绍了两种方法:code

1. 直接实现DisposableBean接口,实现destroy方法便可对象

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

 

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

  

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