轉載自: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 theApplicationContext
closes gracefully on exit. All the standard Spring lifecycle callbacks (such as theDisposableBean
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