I’ve been gradually getting to grips with Spring for a while now and think I have a reasonable idea of the concepts however I came across information in another of my threads which turned things upside down for me…
“…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.”
This got me thinking that I have real use cases where I’d like to use prototype beans where, for example, I need a “new” bean instance per request. However from what I understand of this snippet (from the Spring 3 docs) 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). Furthermore I take it from this that the resources held by the prototype bean have to be manually cleaned up.
Can somebody let me know if this is correct? If so is there a typical pattern used to deal with this? I’d appreciate an answer which could describe the architectural reason why Spring implements prototype beans in this manner.
Yes, but the container does not hold references to prototype-scoped beans. This is the reason why destruction callbacks are not called: Spring creates bean instance, wires it and calls construction callbacks. It gives an instance and forgets about that bean.
You can safely create prototype-scoped beans per request. Spring will give you an instance and the moment you don’t have any references to that bean (Spring does not keep one!), it will be garbage collected. But since Spring doesn’t know anything about your bean after creating it – it can’t call any destruction callback. In fact this this boils down to a question: why Java doesn’t have destructors.
So how do you clean up prototype-scoped beans? Well, just like you clean up any other resources in Java – explicitly. Provide
close(),destroy(),stop()or whatever name you like (consider implementingCloseable. Note that such methods aren’t typically needed. Garbage collector will release the whole object graph while persistent resource like database connections will be closed when the wholeDataSourceis closed.