Spring Prototype Bean Scope Example

Tech Lead & Architect | 13+ Years in Cloud, Backend, and AI - Experienced software engineer with expertise in Java, Spring Boot, Microservices, Angular, React, Kafka, DevOps, Python, PySpark, Databricks, and Generative AI. Certified in TOGAF, AWS, and Google Cloud. Passionate about building scalable, secure, and high-performance systems. Enthusiast in Data Engineering & Agentic AI. Author of 1,200+ technical articles sharing insights across diverse tech stacks.
Date: 2018-09-27
Understanding Bean Scopes in the Spring Framework: A Deep Dive into Prototype Beans
The Spring Framework, a widely used Java application framework, provides a powerful mechanism for managing the lifecycle and dependencies of objects, known as beans. A crucial aspect of bean management is the concept of bean scopes, which determine how many instances of a bean are created and how they are shared within the application. This article will explore the different bean scopes available in Spring, with a particular focus on the Prototype scope and its implications for application design.
Spring defines five primary bean scopes: singleton, prototype, request, session, and application. While all have their uses, singleton and prototype are the most fundamental and readily available across various Spring container implementations.
The singleton scope, the default in Spring, ensures that only one instance of a bean is created throughout the application's lifecycle. This instance is shared across all requests and components requiring that bean. While this promotes efficiency and reduces object creation overhead, it’s crucial to understand that singleton beans are inherently stateless. Any changes made to a singleton bean's internal state persist across all users or components, potentially leading to unexpected behavior and data corruption if the bean is designed to hold mutable state.
In contrast, the prototype scope dictates that a new instance of the bean is created each time a request is made for it. This is fundamentally different from the singleton approach. Each component or user receives a unique, independent copy of the prototype bean, thereby preventing data conflicts and preserving state integrity between different interactions. This makes the prototype scope ideal for beans that need to manage their own internal state and interact with data unique to each request.
The remaining scopes—request, session, and application—are specifically tailored to web applications. A request-scoped bean exists only for the duration of a single HTTP request. Similarly, a session-scoped bean has a lifespan tied to a user's web session, while application-scoped beans live for the entire lifetime of the web application. These specialized scopes are crucial for managing data tied to specific web interactions but fall outside the core focus of this article on prototype beans.
Consider a scenario involving a data processing bean. If this bean needs to maintain data specific to each user or process, a singleton scope would be disastrous. The shared instance would corrupt its internal state for each subsequent user. Using a prototype scope, however, guarantees that each user receives a fresh instance of the bean, ensuring data integrity and preventing unexpected interactions. This is why prototype scope is preferred for stateful beans.
However, the prototype scope also comes with a crucial responsibility: the Spring container does not manage the destruction lifecycle of prototype beans. Unlike singleton beans, which are managed by the container from creation to destruction, prototype beans are the sole responsibility of the application code. This means you must explicitly manage the resources held by a prototype bean, ensuring they are released and cleaned up when they are no longer needed. This prevents resource leaks and ensures optimal application performance. Failure to properly manage prototype bean resources can lead to significant problems, especially in long-running applications.
Creating and Configuring Prototype Beans
Spring provides several ways to define a bean as a prototype. Traditionally, this was accomplished through XML-based configuration files. A developer would specify the scope attribute within the bean definition element, setting it to "prototype". The XML file would then detail the bean’s class and any dependencies it might have. The Spring container would then use this configuration to create and manage the bean's lifecycle according to its specified scope.
With the rise of Java-based configuration, using annotations like @Scope provides a more modern approach. The @Scope annotation, applied directly to the bean class definition, allows developers to concisely specify the bean's scope using the value attribute. To create a prototype bean using this method, one would set value to ConfigurableBeanFactory.SCOPE_PROTOTYPE. This annotation-based approach is cleaner and more integrated within the application code, improving readability and maintainability.
Regardless of whether XML or annotations are used, the core principle remains the same: clearly define the scope to ensure the Spring container correctly manages the creation of new instances in response to requests.
An Illustrative Example
Imagine a simple Message class with fields to hold a message text and a sender name. To illustrate the prototype scope's behavior, let's create two instances of this Message bean and observe their independent states. When using the prototype scope, calling the bean from different parts of your application would yield two separate Message objects, each with its own unique data, independent of the others. A singleton version would cause modifications made by one part of the application to be visible to all other parts. It is this crucial difference that highlights the utility of the prototype scope.
The configuration of the bean, whether through XML or annotations, would declare the Message class and explicitly set its scope to prototype. Application code would then request instances of the Message bean, and the Spring container would reliably deliver a fresh instance for each request, ensuring complete isolation between the instances and their internal state.
Conclusion
The choice between singleton and prototype bean scopes depends entirely on the nature of the bean itself. Stateless beans, those whose internal state doesn't change or affect other users, thrive in the singleton scope's efficiency. However, stateful beans, those that need to maintain individual state per request or user, require the prototype scope to guarantee data integrity and prevent unintended consequences. Understanding these fundamental differences and the associated implications for resource management is critical for building robust and scalable Spring applications. While the prototype scope introduces the added responsibility of explicit resource cleanup, the benefits of data isolation and independent state often outweigh the added development effort. A well-designed Spring application skillfully balances the advantages of both singleton and prototype scopes to optimize performance and prevent errors arising from shared state.