如何在Spring中正确关闭ApplicationContext?

时间:2015-03-20 15:16:01

标签: java spring spring-mvc applicationcontext

我正在攻读Spring Core认证,我对这个提供的学习材料中的问题有一些了解:

  

关闭应用程序上下文的首选方法是什么?

我知道如果我有这样的事情:

ConfigurableApplicationContext context = …
// Destroy the application
context.close();

通过在上下文对象上使用 close()方法,关闭ApplicationContext并销毁应用程序。

但我认为这不是我必须做的最佳方式。

阅读官方文档我发现我也可以这样做:

context.registerShutdownHook();

使用JVM注册Shutdown Hook ,因此JVM将在JVM退出之前触发Spring的关闭阶段。所以在JVM退出时,Spring的关闭阶段将会执行。

在文档中,我可以读到:通常无法调用context.close(),因为许多应用程序(Web应用程序)无限期运行但是这最后一个断言的确切意味着什么?为什么Web应用程序无限期运行?

所以我的问题是:

  • 我是否可以使用第二种方式关闭应用程序上下文而不是Web应用程序?
  • 是否优先尊重context.close()

TNX

3 个答案:

答案 0 :(得分:11)

如您所知ContextLoaderListener是负责初始化和销毁​​ApplicationContext的那个,当您关闭服务器时,会调用ContextLoaderListener的contextDestroyed方法。

  public void contextDestroyed(ServletContextEvent event){
    closeWebApplicationContext(event.getServletContext());
    ContextCleanupListener.cleanupAttributes(event.getServletContext());
  }

closeWebApplicationContext中,他们实际上在ApplicationContext上调用close方法,就像这样

  if ((this.context instanceof ConfigurableWebApplicationContext)) {
    ((ConfigurableWebApplicationContext)this.context).close();
  }

直接来自spring-web-4.1.5.jar。从这里可以看出,他们使用close来破坏Web应用程序中的ApplicationContext。

但是registerShutdownHook用于显式关闭非Web应用程序中的IoC容器,就像独立的桌面应用程序一样,特别是当您从ClassPathXmlApplicationContext(或)FileSystemXmlApplicationContext(或)手动创建ApplicationContext时其他类型。

这样做是为了释放spring应用程序使用的所有资源,并在你的spring bean上调用destroy方法(如果有的话)。

答案 1 :(得分:8)

  

在文档上我可以读到:通常无法调用context.close(),因为许多应用程序(Web应用程序)无限期地运行但是这最后一个断言的确切含义是什么?为什么Web应用程序无限期运行?

只要部署它的应用程序服务器运行,Web应用程序就会运行。由应用程序服务器(而不是您)来正确启动和停止应用程序。这意味着当应用程序服务器停止时,servlet上下文将被销毁。在Spring应用程序中,web.xml中注册的ContextLoaderListener类侦听此事件(已销毁的上下文)以正确关闭Spring上下文。

在应用程序服务器外部使用Spring(如独立应用程序)时,您可以正确停止Spring上下文。正如您所说,这可以通过显式调用context.close()或注册一个为您调用此函数的关闭挂钩(context.registerShutdownHook())来完成。

答案 2 :(得分:0)

来自https://stackoverflow.com/a/42018369

ApplicationContext类并未将这两种方法中的任何一种定义为其接口的一部分,但是ConfigurableApplicationContext确实定义了这两种方法。

来自JavaDoc:

close()-关闭此应用程序上下文,销毁其bean工厂中的所有bean。 registerShutdownHook() -在JVM运行时中注册一个关闭挂钩,除非当时已经关闭了该上下文,否则在JVM关闭时将其关闭。 基本上,AbstractApplicationContext#close()将在调用时关闭或关闭ApplicationContext,而AbstractApplicationContext#registerShutdownHook()将在以后的某个时间关闭或关闭ApplicationContext。 JVM由于任何原因而关闭。这将通过利用JVM关闭挂钩功能来实现。

在任何一种情况下,实际关闭都是通过doClose()方法完成的。

如果您对输出为何如此相似感到好奇,那是因为无论您在示例的第3行中调用close()还是registerShutdownHook(),它们都在有效地完成相同的事情。 close()将立即关闭,而registerShutdownHook()将在JVM退出之前关闭,这几乎是在方法被调用后立即关闭,因为这是最后一行代码!