为什么 SmartLifecycle 组件没有关闭?

Why are SmartLifecycle components not shutting down?

在我 Tomcat 的网络应用 运行 中,我有两个 Spring 5.0.2 类 实现了 SmartLifecycle。它们按预期开始,但不会停止。我在日志文件中看到以下内容:

INFO o.s.c.s.DefaultLifecycleProcessor$LifecycleGroup [localhost-startStop-2] Stopping beans in phase 2147483647
DEBUG o.s.c.s.DefaultLifecycleProcessor [localhost-startStop-2] Asking bean 'myQueue1' of type ... to stop
DEBUG o.s.c.s.DefaultLifecycleProcessor [localhost-startStop-2] Asking bean 'myQueue2' of type ... to stop
WARN o.s.c.s.DefaultLifecycleProcessor$LifecycleGroup [localhost-startStop-2] Failed to shut down 2 beans with phase value 2147483647 within timeout of 30000: [myQueue1, myQueue2]

我是 运行 调试器中的 Java 进程,我没有在 stop() 方法中的第一行断点(另一个写入日志).

这是我实现的与停止相关的 SmartLifeCycle 方法(两者都相同 类)。为什么 stop 没有被执行?也欢迎任何调试提示。

@Component
@Scope(value = "singleton")
public class MyQueue1 implements SmartLifecycle
{

@Override
public void stop(Runnable runnable) {
}

@Override
public void stop() {
    logger.info("Stop for " + queueName);
}

@Override
public boolean isRunning() {
    return queueThread != null;
}

@Override
public int getPhase() {
    return Integer.MAX_VALUE; // Suggest last to start; first to stop
}

}

您的依赖项可能会影响生命周期。

来自 Spring 文档:

Any explicit "depends-on" relationship will take precedence over the phase order such that the dependent bean always starts after its dependency and always stops before its dependency.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/SmartLifecycle.html

Spring 保持闩锁倒计时,以确保所有 "stop" 方法都已完成。这是来自 DefaultLifeCycleProcessor.java

的一段代码
((SmartLifecycle)bean).stop(new Runnable() {
                            public void run() {
                                latch.countDown();
                                countDownBeanNames.remove(beanName);
                                if(DefaultLifecycleProcessor.this.logger.isDebugEnabled()) {
                                    DefaultLifecycleProcessor.this.logger.debug("Bean '" + beanName + "' completed its stop procedure");
                                }
                            }
                        });

所以在你的代码中,因为你没有在传递的 runnable 中调用这个 "run" 方法,因此在 DefaultLifecycleProcessor.java 中执行下面的代码时,闩锁倒计时值大于 0。因此,您将收到 "failed.." 警告日志。

try {
                    latch.await(this.timeout, TimeUnit.MILLISECONDS);
                    if(latch.getCount() > 0L && !countDownBeanNames.isEmpty() && DefaultLifecycleProcessor.this.logger.isWarnEnabled()) {
                        DefaultLifecycleProcessor.this.logger.warn("Failed to shut down " + countDownBeanNames.size() + " bean" + (countDownBeanNames.size() > 1?"s":"") + " with phase value " + this.phase + " within timeout of " + this.timeout + ": " + countDownBeanNames);
                    }
                } catch (InterruptedException var5) {
                    Thread.currentThread().interrupt();
                }

现在,要解决问题,请在 stop(Runnable runnable) 方法中调用以下方法。

runnable.run();