我已经逐渐掌握了Spring一段时间,并且认为我对这些概念有一个合理的想法,但是我在另一个线程中遇到了信息,这让我的事情变得颠倒了……
“…although initialization lifecycle callback methods are called on all objects regardless of scope,in the case of prototypes,configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding. To get the Spring container to release resources held by prototype-scoped beans,try using a custom bean post-processor,which holds a reference to beans that need to be cleaned up.”
这让我觉得我有真正的用例,我想使用原型bean,例如,我需要每个请求一个“新”bean实例.但是根据我对这个片段的理解(来自Spring 3文档),Spring坚持引用需要清理的bean(引用本身意味着bean不会被垃圾收集器自动清除).此外,我认为必须手动清理原型bean所拥有的资源.
如果这是正确的,有人可以告诉我吗?如果是这样,有一个典型的模式来处理这个?我很欣赏一个答案,它可以描述Spring以这种方式实现原型bean的架构原因.
Spring holds on to a reference to beans that need to be cleaned up (the reference itself meaning that the bean will not be cleared automatically by the garbage collector).
是的,但容器不包含对原型范围bean的引用.这就是为什么不调用销毁回调的原因:Spring创建bean实例,连接它并调用构造回调.它给出了一个实例并忘记了那个bean.
您可以安全地为每个请求创建原型范围的bean. Spring会给你一个实例,当你没有任何对bean的引用时(Spring没有保留一个!),它将被垃圾收集.但是因为Spring在创建它之后对你的bean一无所知 – 它不能调用任何破坏回调.事实上,这归结为一个问题:为什么Java没有析构函数.
那你如何清理原型范围的豆子呢?好吧,就像你清理Java中的任何其他资源一样 – 明确地说.提供close(),destroy(),stop()或任何你喜欢的名称(考虑实现Closeable
.注意,通常不需要这样的方法.垃圾收集器将释放整个对象图,而数据库连接等持久资源将被关闭时整个DataSource已关闭.