Spring ApplicationContext - 资源泄漏:'context'永远不会关闭

zig*_*ggy 91 java eclipse spring spring-mvc

在spring MVC应用程序中,我使用以下方法初始化其中一个服务类中的变量:

ApplicationContext context = 
         new ClassPathXmlApplicationContext("META-INF/userLibrary.xml");
service = context.getBean(UserLibrary.class);
Run Code Online (Sandbox Code Playgroud)

UserLibrary是我在我的应用程序中使用的第三方实用程序.上面的代码为'context'变量生成警告.警告如下所示:

Resource leak: 'context' is never closed
Run Code Online (Sandbox Code Playgroud)

我不明白这个警告.由于应用程序是一个Spring MVC应用程序,因此当我在应用程序运行时引用该服务时,我无法真正关闭/销毁上下文.试图告诉我的警告究竟是什么?

Mar*_*tör 88

由于应用程序上下文是ResourceLoader(即I/O操作),因此它消耗了在某些时候需要释放的资源.这也是一个扩展AbstractApplicationContext,它实现Closable.因此,它有一个close()方法,可以在try-with-resources语句中使用.

try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/userLibrary.xml")) {
  service = context.getBean(UserLibrary.class);
}
Run Code Online (Sandbox Code Playgroud)

你是否真的需要创建这个上下文是一个不同的问题(你链接到它),我不会对此发表评论.

确实,当应用程序停止时,上下文会被隐式关闭,但这不够好.Eclipse是对的,您需要采取措施为其他情况手动关闭它,以避免类加载器泄漏.

  • 值得注意的是:虽然基础`ApplicationContext`接口不提供`close()`方法,但是`ConfigurableApplicationContext`(`ClassPathXmlApplicationContext`实现)实现并扩展`Closeable`来启动,所以你可以使用Java 7试试资源范式. (25认同)
  • 在这里给@kbolino的评论+1,因为我把我的变量声明为`ApplicationContext`并且在我看到为什么我没有接近可用的方法时收到警告的时候... (3认同)

usr*_*ΛΩΝ 39

close()未在ApplicationContext界面中定义.

安全摆脱警告的唯一方法如下

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...);
try {
    [...]
} finally {
    ctx.close();
}
Run Code Online (Sandbox Code Playgroud)

或者,在Java 7中

try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...)) {
    [...]
}
Run Code Online (Sandbox Code Playgroud)

基本区别在于,由于您明确地实例化了上下文(即使用new),因此您知道要实例化的类,因此您可以相应地定义变量.

如果您没有实例化AppContext(即使用Spring提供的那个),那么您无法关闭它.

  • 一次又一次错误的尝试......终于被教给别人......`新的ClassPathXmlApplicationContext(...);`必须在try-block之外.然后就不需要空检查了.如果构造函数抛出异常,则`ctx`为null,并且不调用`finally`块(因为异常是在try-block之外抛出的).如果构造函数没有抛出异常,则输入`try`块并且`ctx`不能为null,因此不需要进行空检查. (6认同)

小智 12

一个简单的演员解决了这个问题:

((ClassPathXmlApplicationContext) fac).close();
Run Code Online (Sandbox Code Playgroud)


Ash*_*tav 6

由于Application上下文具有ClassPathXmlApplicationContext的实例,因此它具有close()方法.我只需要CAST appContext对象并调用close()方法,如下所示.

ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
//do some logic
((ClassPathXmlApplicationContext) appContext).close();
Run Code Online (Sandbox Code Playgroud)

这将修复资源泄漏警告.