Manually Destroy Prototype Spring Bean
In Spring Framework, beans can be defined with different scopes. The most common scopes are singleton
and prototype
. While singleton beans are managed by the Spring container for their entire lifecycle, prototype beans are different. In Spring, when dealing with a prototype bean, the container does not manage the bean’s entire lifecycle, which means you may need to manually destroy the bean instance after use to free up resources. Let’s delve into understanding how this process works.
1. Prototype Bean and Its Lifecycle
A prototype bean in Spring is created each time it is requested. Unlike singleton beans, which are created only once per Spring container, a new instance of a prototype bean is created every time a new request is made for it. This means that the Spring container does not maintain a reference to the prototype beans once they are created and injected.
The lifecycle of a prototype bean is much shorter than that of a singleton. Spring is only responsible for creating and initializing the prototype bean. After the initialization phase, the responsibility for the bean’s lifecycle management (including destruction) is transferred to the client code that requested the bean.
1.1 Do Prototype Beans Need Manual Destruction?
Yes, prototype beans need to be destroyed manually. Since the Spring container does not manage the full lifecycle of a prototype bean, it is not responsible for invoking any destruction callbacks, such as those defined by @PreDestroy
or DisposableBean
. It is up to the developer to ensure that the prototype bean is properly cleaned up.
1.2 How to Destroy Prototype Bean?
There are several ways to handle the destruction of prototype beans manually in Spring. The most common approaches include:
- Managing the lifecycle of the bean explicitly in the client code.
- Using Spring’s
BeanFactory
to control the destruction. - Registering the bean for destruction with a custom callback.
1.3 Difference Between Singleton and Prototype Bean
Aspect | Singleton Bean | Prototype Bean |
---|---|---|
Definition | A single instance of the bean is created by the Spring container and shared across the entire application. | A new instance of the bean is created every time it is requested from the Spring container. |
Bean Scope | Singleton scope (default scope in Spring). | Prototype scope. |
Instance Creation | One instance per Spring container is created at application startup. | Multiple instances are created, one for each request. |
Lifecycle Management | Managed entirely by the Spring container (creation, initialization, and destruction). | Spring container is only responsible for creation and initialization. Destruction is handled manually. |
Usage | Best for stateless beans or beans shared across the application. | Best for stateful beans where a new instance is needed for each use. |
Destruction | Spring container automatically manages destruction, including calling @PreDestroy methods. | Needs to be destroyed manually; Spring does not call @PreDestroy methods. |
Performance | More efficient since only one instance is created and shared. | Less efficient due to the creation of new instances on every request. |
2. Code Example: Destroying a Prototype Bean
Let’s consider a simple example of a prototype bean:
@Configuration public class AppConfig { @Bean @Scope("prototype") public MyPrototypeBean myPrototypeBean() { return new MyPrototypeBean(); } } public class MyPrototypeBean { public void initialize() { System.out.println("Prototype bean initialized."); } public void destroy() { System.out.println("Prototype bean was destroyed."); } }
In the above code, we define a bean with prototype scope using @Scope("prototype")
. The MyPrototypeBean
class has two methods: initialize()
and destroy()
. However, the destroy method will not be called automatically by the Spring container.
2.1 Manual Destruction in Client Code
We can destroy the bean manually by calling the destroy()
method directly after its use:
public class PrototypeBeanClient { @Autowired private ApplicationContext context; public void usePrototypeBean() { MyPrototypeBean bean = context.getBean(MyPrototypeBean.class); bean.initialize(); // Use the bean for some business logic // Manually destroy the prototype bean bean.destroy(); } }
Here, after fetching the prototype bean from the application context, we manually call the destroy()
method when we’re done using the bean. The code logs the following output:
Prototype bean initialized. Prototype bean was destroyed.
2.2 Using Spring’s BeanFactory for Destruction
If you want a more elegant solution, Spring’s ConfigurableBeanFactory
can be used to destroy prototype beans. Here’s how:
@Component public class PrototypeBeanClient { @Autowired private ConfigurableBeanFactory beanFactory; public void usePrototypeBean() { MyPrototypeBean bean = (MyPrototypeBean) beanFactory.getBean(MyPrototypeBean.class); bean.initialize(); // Use the bean // Register bean for destruction beanFactory.destroyBean(bean); } }
In this case, Spring’s ConfigurableBeanFactory
is used to destroy the bean properly. This method registers the prototype bean for destruction after its usage.
3. Conclusion
Unlike singleton beans, prototype beans in Spring are not managed for their entire lifecycle. The Spring container does not handle the destruction of prototype beans automatically, so they need to be destroyed manually. This can be achieved by calling the bean’s destroy()
method or using Spring’s BeanFactory
for more controlled destruction. Ensuring proper destruction of prototype beans is crucial in applications that rely on resources like file handles, sockets, or database connections, which need explicit cleanup.