【问题标题】:Spring - How can I destroy my prototype-scoped beans?Spring - 如何销毁原型范围的 bean?
【发布时间】:2011-12-23 17:05:52
【问题描述】:

我有一个单例 bean,它有一个创建原型 bean 实例的方法。我正在使用方法documented here 来获取原型bean 的实例。

public class SingletonService implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void go() {

        MyPrototypeBean prototype = applicationContext
            .getBean(MyPrototypeBean.class);

        prototype.doSomething();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {

        this.applicationContext = applicationContext;
    }
}

起初我认为这已经足够好了,当 'go' 方法返回时,我的 'prototype' 实例将超出范围,这意味着该实例将没有引用并且会被垃圾回收。

但是,一位同行指出the documentation的以下声明:

客户端代码必须清理原型范围的对象并发布 原型 bean 持有的昂贵资源。

所以听起来 Spring 会保留一个引用,所以 gc 永远不会拾取它?如果是这种情况,我如何告诉 Spring 释放引用?文档提到我可以使用“自定义 bean 后处理器”,但不清楚该处理器适用于何处以及它将运行什么代码。

提前感谢大家的帮助, 罗伊

【问题讨论】:

  • 感谢您的精彩问题。您是否添加了一些额外的代码来手动破坏原型 bean?如果是,那你能解释一下吗?

标签: spring garbage-collection


【解决方案1】:

我认为您误解了文档。只是说Spring不会管理原型bean的生命周期,因此@PreDestroy(等)方法需要由您自己的代码调用。 Spring 不会保留引用。

【讨论】:

  • 感谢 Art - 所以可以肯定地说上面的代码已经足够了,不会是内存泄漏的原因吗?
  • 嗯,这取决于 MyPrototypeBean 的实现,但从 Spring 的角度来看,这很好。
  • 为了检索 bean,你使用了 getBean(..) 方法。我知道表演的成本很高。那你应该怎么找回呢?
【解决方案2】:

只是为了让上述 artbristol 的回答更加清晰:artbristol 是正确的。 Spring 将创建您的代码所需的原型 bean,但不会销毁它。这种行为是设计使然,因为一旦超出范围,允许垃圾收集器“拾取”原型依赖项被认为更有效。如果不是以这种方式完成,那么唯一的另一种选择是让 Spring 容器在创建原型 bean 时保留对原型 bean 的每个实例的引用。鉴于您的代码在每次调用它时都会创建一个新的 MyPrototypeBean 实例,这意味着您可能有太多的 MyPrototypeBean 实例正在生成、收集但没有被销毁,因为只有在 Spring 容器关闭时才会发生销毁。您可以理解,这很容易导致快速的内存泄漏。

因此,原型 bean 由垃圾收集器处理,在超出范围或手动调用其销毁方法时被销毁。

文档的意思是,如果 MyPrototypeBean 持有任何资源,例如数据库连接,那么这将阻止该资源被正确释放。因此,管理这一点成为编码人员的责任。

【讨论】:

    猜你喜欢
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多