SpringShutdownHook

SpringShutdowHook与RocketMq等中使用的Hook不一样,它不是传统意义上的钩子函数接口,而是一个线程,这个线程被注册在RunTime类中,RunTime再把它注册到ApplicationShutdownHooks类中,在调用Shutdown.exit和Shutdown.shutdown时,会启动ShutdownApplicationShutdownHooks中的所有Hook,并把他们join到当前线程中。

Shutdown.exit与Shutdown.shutdown的调用时机:
exit:程序主动调用System.exit或因为异常退出时,调用此方法,它在方法末尾会发送一个halt命令告诉JVM强制关闭。
shutdown:程序正常结束,最后一个非守护线程也被销毁后,调用此方法,它不会发送任何命令,只是做一些常规的回收。
在最后程序结束时,所有Hook线程都是并发运行的。

SpringShutdownHook在Spring生命容器中的生命周期:
该Hook在ApplicationContext加载完所有的Bean,所有的postProcessor都被执行完毕,并且执行完毕所有的postConstruct,ApplicationContextRefreshEvent事件已经发布后,该Hook被注册到Shutdown中。

SpringShutdownHook的执行过程就是执行ApplicationContext.doClose()方法

protected void doClose() {
		// Check whether an actual close attempt is necessary...
		if (this.active.get() && this.closed.compareAndSet(false, true)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Closing " + this);
			}

			LiveBeansView.unregisterApplicationContext(this);

			try {
				// 发布ContextClosedEvent
				publishEvent(new ContextClosedEvent(this));
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
			}

			//主动调用所有实现了Lifecycle的Bean对象的stop方法.
			if (this.lifecycleProcessor != null) {
				try {
					this.lifecycleProcessor.onClose();
				}
				catch (Throwable ex) {
					logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
				}
			}

			// 销毁所有单例对象.
			destroyBeans();

			// 销毁BeanFactory.
			closeBeanFactory();

			// 子类实现,默认什么也不做.
			onClose();

			// 将所有监听器删除,只保留Spring默认的监听器.
			if (this.earlyApplicationListeners != null) {
				this.applicationListeners.clear();
				this.applicationListeners.addAll(this.earlyApplicationListeners);
			}

			// Switch to inactive.
			this.active.set(false);
		}
	}

模仿Spring的ShutdownHook,自己实现一个ShutdownHook:

public static void main(String[] args) {
        //localhost:9081/....
        SpringApplication.run(ApplicationStarter.class,args);
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我也监听到了关闭事件");
            }
        }));

        Thread thread = new Thread(()->{
            try {
                Thread.sleep(10*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.exit(1);
        });
        thread.start();
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值