16
votes

I've got a singleton bean that has a method that creates instances of a prototype bean. I'm using the method documented here to get instances of the prototype 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;
    }
}

At first I thought that this was good enough, that my instance of 'prototype' would go out of scope when the 'go' method returned, meaning that the instance would have not reference and would be garbage collected.

However, a peer pointed out the following statement from the documentation:

The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding.

So it sounds like Spring will retain a reference, and so the gc will never pick it up? If that's the case how do I tell Spring to release the reference? The documentation mentions that I can use a 'custom bean post-processor', but it's not clear where that processor would fit in and what code it would run.

Thanks all in advance for helping out, Roy

2
Thanks for your Brilliant question. Have you add some extra code for manually destructing the prototype bean? If yes, then can you please explain? - Md. Sajedul Karim

2 Answers

11
votes

I think you're misunderstanding the documentation. It's just saying Spring won't manage the lifecycle of the prototype bean, so @PreDestroy (etc.) methods need to be called by your own code. Spring won't retain a reference.

1
votes

Just to add some clarity to artbristol's answer above: artbristol is correct. Spring will create the prototype bean required by your code, but will not destroy it. This behaviour is by design as it is considered to be more effective to allow the garbage collector to 'pick up' your prototype dependency once it goes out of scope. If it was not done this way, then the only other alternative would be for Spring container to retain a reference to each and every instance of your prototype bean as they are created. Given that your code creates a NEW instance of MyPrototypeBean bean each time it is called, this means you could potentially have too many instances of MyPrototypeBean being generated, collecting but not being destroyed because destruction only occurs with the closing of the Spring Container. You can appreciate that this could very easily lead to a rapid memory leak.

As a result, it is by design that prototype beans are handled by the garbage collector, being destroyed as and when they go out of scope OR when their destruction methods are manually called.

What the documentation is saying is that IF MyPrototypeBean is holding onto any resources such as a database connection, then this will prevent that resource being properly released. It therefore becomes the coder's responsibility to manage this.