春天原型豆和春天的好处

JLo*_*ove 8 java architecture spring garbage-collection

我已经逐渐掌握了Spring一段时间,并且认为我对这些概念有一个合理的想法,但是我在另一个线程中遇到了信息,这让我的事情变得颠倒了......

"...虽然无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调.客户端代码必须清理原型范围的对象并释放原型bean的昂贵资源为了让Spring容器释放原型范围的bean所拥有的资源,尝试使用自定义bean后处理器,它包含对需要清理的bean的引用."

这让我觉得我有真正的用例,我想使用原型bean,例如,我需要每个请求一个"新"bean实例.但是根据我对这个片段的理解(来自Spring 3文档),Spring坚持引用需要清理的bean(引用本身意味着bean不会被垃圾收集器自动清除).此外,我认为必须手动清理原型bean所拥有的资源.

如果这是正确的,有人可以告诉我吗?如果是这样,有一个典型的模式来处理这个?我很欣赏一个答案,它可以描述Spring以这种方式实现原型bean的架构原因.

Tom*_*icz 18

Spring坚持对需要清理的bean的引用(引用本身意味着bean不会被垃圾收集器自动清除).

是的,但容器不包含对原型范围bean的引用.这就是为什么不调用销毁回调的原因:Spring创建bean实例,连接它并调用构造回调.它给出了一个实例并忘记了那个bean.

您可以安全地为每个请求创建原型范围的bean.Spring会给你一个实例,当你没有任何对bean的引用时(Spring没有保留一个!),它将被垃圾收集.但是因为Spring在创建它之后对你的bean一无所知 - 它不能调用任何破坏回调.事实上,这归结为一个问题:为什么Java没有析构函数.

那你如何清理原型范围的豆子呢?好吧,就像你清理Java中的任何其他资源一样 - 明确地说.提供close(),destroy(),stop()或者你喜欢的任何名称(考虑实施Closeable.请注意,不是通常需要这样的方法.垃圾收集器将释放整个对象图,而当整个像数据库连接持久性资源将被关闭DataSource关闭.


JB *_*zet 8

你误读了文档.它明确地说:

要使Spring容器释放原型范围的bean所拥有的资源,请尝试使用自定义bean后处理器,它包含对需要清理的bean的引用.

所以Spring没有对它创建的原型bean有任何引用.由您来创建一个bean后处理器,如果需要,它将保存对这些bean的引用.

而且,原型bean很少能够保存必须清理的资源.例如,连接池(需要在关闭时正确销毁)通常是单例bean.将它作为原型是没有多大意义的.由于原型bean通常使用的时间很短,因此创建它的客户端可以在不再使用它时明确释放其资源.就像创建新流或连接时一样,并在finally块中关闭它.


Fra*_*eth 5

Spring不了解使用原型范围创建的所有实例。它将仅实例化和配置原型范围内的bean,然后将其移交给客户端,如文档中所述。

Spring不能管理原型bean的完整生命周期:容器会实例化,配置,装饰和以其他方式组装原型对象,将其交给客户端,然后对该原型实例不再有任何了解。

http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s04.html#beans-factory-scopes-prototype