Java 如何在Spring中正确关闭ApplicationContext?
我正在学习Spring Core认证,在提供的学习材料中,我对这个问题有一些疑问: 关闭应用程序上下文的首选方式是什么 我知道如果我有这样的东西:Java 如何在Spring中正确关闭ApplicationContext?,java,spring,spring-mvc,applicationcontext,Java,Spring,Spring Mvc,Applicationcontext,我正在学习Spring Core认证,在提供的学习材料中,我对这个问题有一些疑问: 关闭应用程序上下文的首选方式是什么 我知道如果我有这样的东西: ConfigurableApplicationContext context = … // Destroy the application context.close(); context.registerShutdownHook(); 通过在上下文对象上使用close()方法,ApplicationContext被关闭,应用程序被销毁 但我认为
ConfigurableApplicationContext context = …
// Destroy the application
context.close();
context.registerShutdownHook();
通过在上下文对象上使用close()方法,ApplicationContext被关闭,应用程序被销毁
但我认为这不是我做这件事的最好方式
阅读官方文件后,我发现我也可以这样做:
ConfigurableApplicationContext context = …
// Destroy the application
context.close();
context.registerShutdownHook();
在JVM中注册一个关闭钩子,因此JVM将在JVM退出之前触发Spring的关闭阶段。所以在JVM退出时,将执行Spring的关闭阶段
在文档中我可以读到:通常不可能调用context.close()
,因为许多应用程序(web应用程序)无限期运行,但这最后一个断言的确切含义是什么?为什么web应用程序无限期运行
因此,我的问题是:
- 我是否可以使用第二种方法关闭应用程序上下文,而不是关闭web应用程序
- 是否优先考虑
上下文.close()
web.xml
中注册的类侦听此事件(上下文已销毁)以正确关闭Spring上下文
在应用服务器之外使用Spring时(如独立应用程序),正确停止Spring上下文取决于您。正如您所说,这可以通过显式调用
context.close()
或注册一个为您进行此调用的关闭钩子(context.registerSutdownhook()
)来实现。正如您所知,ContextLoaderListener
负责初始化和销毁您的应用程序上下文,关闭服务器时,将调用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应用程序中的应用程序上下文
但是,registerShutdownHook
用于显式关闭非web应用程序中的IoC容器,例如独立桌面应用程序,特别是当您从ClassPathXmlApplicationContext(或)FileSystemXmlApplicationContext(或)其他类型手动创建ApplicationContext时
这样做是为了释放spring应用程序使用的所有资源,并在spring bean上调用destroy方法(如果有的话)。来自:
ApplicationContext
类没有将这两种方法定义为其接口的一部分,但是ConfigurableApplicationContext
确实定义了这两种方法
从JavaDoc:
close()
——关闭此应用程序上下文,销毁其bean工厂中的所有bean。
registerShutdownHook()
——在JVM运行时注册一个关闭钩子,在JVM关闭时关闭此上下文,除非当时它已经关闭。
基本上,AbstractApplicationContext#close()
将在调用时关闭ApplicationContext
,而AbstractApplicationContext#registerSuttonHook()
将在稍后JVM出于任何原因关闭时关闭或关闭ApplicationContext
。这将通过利用JVM关闭挂钩功能来实现
在这两种情况下,实际关闭都是通过doClose()
方法完成的
如果您想知道为什么您的输出看起来如此相似,那是因为它们实际上在做相同的事情,无论您在示例的第3行调用
close()
还是registerShutdownHook()
close()
将立即关闭,registerShutdownHook()
将在JVM退出之前关闭,这几乎是在调用该方法后立即关闭,因为它是最后一行代码 许多应用程序(web应用程序)无限期运行
。它通常指在无限循环中发生的事情,除非您停止该过程,例如您的SocketServer侦听传入请求。首先,为什么要手动关闭WebApplicationContext?它通常是在服务器启动时创建的,在服务器关闭时销毁。web应用程序永远不会停止,因为如果这样做,站点就会关闭。若要停止运行web应用程序,将关闭它(例如,通过停止web服务器)。当您这样做时,JVM也会停止,因此“关闭JVM的钩子”是关闭JVM上下文的方法。为什么要停止上下文?close用于web应用程序,而shutDownHook用于独立应用程序。刚刚发布了我的答案,但没有更多细节:)好的,但是它是context.registerShutdownHook()比context.close()好吗?和方法都调用相同的代码来关闭Spring上下文。您可以在AbstractApplicationContext
中看到这一点。在独立应用程序中,例如后台服务或桌面应用程序,当您输入main方法时,您将创建应用程序上下文,现在我的问题是,如果您注册