Spring - 如何销毁原型范围的bean?

时间:2011-12-23 17:05:52

标签: spring garbage-collection

我有一个单例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后处理器”,但不清楚该处理器适合的位置以及它将运行的代码。

先谢谢大家帮忙, 罗伊

2 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:0)

只是为上述artbristol的回答增加一些清晰度:artbristol是正确的。 Spring将创建代码所需的原型Bean,但不会破坏它。此行为是设计使然,因为它被认为更有效地允许垃圾收集器在超出范围时“拾取”原型依赖项。如果不是这样,那么Spring容器的唯一其他选择就是在创建原型bean时保留对原型的每个实例的引用。假设您的代码每次调用都会创建一个MyPrototypeBean bean的NEW实例,这意味着您可能会生成,收集但不会销毁MyPrototypeBean的实例太多,因为销毁仅在Spring容器关闭时发生。您可以理解,这很容易导致快速的内存泄漏。

结果是,根据设计,原型bean由垃圾收集器处理,在超出范围时被销毁,或者在手动调用销毁方法时被销毁。

文档中所说的是,如果MyPrototypeBean保留了任何资源(例如数据库连接),那么这将阻止该资源被正确释放。因此,管理此任务成为编码人员的责任。