Spring Bean Scopes-tutorial
When working with the Spring Framework, understanding Bean Scopes is essential.
Scopes decide how many instances of a bean Spring creates and how long those instances live inside the application.
If you understand bean scopes, you understand how Spring manages objects internally, which directly impacts memory, performance, and correctness of your application.
Singleton vs Prototype - Live Demo (STS / IntelliJ)
Step 2: Fetch Each Bean Twice
Output
Singleton
Prototype
A. Request Scope
When Should You Use Which Scope?
Let us break down the Spring Bean Scopes in a simple and practical way with a real example that you can run inside STS / IntelliJ.
What is a Bean Scope ?
Let us understand them in details.
What is a Bean Scope ?
A Bean Scope defines the lifecycle and visibility of a Spring bean.
It answers two questions:
- How many bean instances will Spring create?
- When will those instances be created and destroyed?
Spring provides six scopes, but the most commonly used ones are:
- Singleton (default)
- Prototype
- Request (Web)
- Session (Web)
- Application (Web)
- WebSocket (Web)
Let us understand them in details.
1. Singleton Scope (Default Scope)
Singleton is the default scope in Spring.
Spring creates one single instance of the bean for the entire application context.
Every time you inject or request the bean, Spring gives you the same object.
Example
Example
package com.example.quipoin;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Service;
@Service@Scope("singleton")public class MyService {}How it behaves
- Application starts - Spring creates one instance.
- Any component requesting MyService gets the same instance.
- This makes Singleton ideal for:
- Service layer classes
- Repository classes
- Shared utilities
- Stateless components
2. Prototype Scope
In Prototype scope, Spring creates a new bean instance every time it is requested.
Example
package com.example.quipoin;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Service;
@Service@Scope("prototype")public class MyPrototypeService {}When it is created
- Every call to context.getBean() - New object
- Every dependency injection point - New object
- This scope is useful when:
- You need stateful objects
- You require temporary objects
- You want one-time-use beans
Singleton vs Prototype - Live Demo (STS / IntelliJ)
This is the most important practical part.
To truly understand the difference, you must run the code because the change is visible only at runtime.
Step 1: Define the Beans
package com.example.quipoin;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Service;
@Service@Scope("singleton")public class MyService {}package com.example.quipoin;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Service;
@Service@Scope("prototype")public class MyPrototypeService {}Step 2: Fetch Each Bean Twice
package com.example.quipoin;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MyService s1 = context.getBean(MyService.class);
MyService s2 = context.getBean(MyService.class);
MyPrototypeService p1 = context.getBean(MyPrototypeService.class);
MyPrototypeService p2 = context.getBean(MyPrototypeService.class);
System.out.println("Singleton 1: " + s1);
System.out.println("Singleton 2: " + s2);
System.out.println("Prototype 1: " + p1);
System.out.println("Prototype 2: " + p2);
}
}Output
Singleton
Singleton 1: com.example.quipoin.MyService@1caa0244
Singleton 2: com.example.quipoin.MyService@1caa0244- Same memory address
- Same object
- Singleton confirmed
Prototype
Prototype 1: com.example.quipoin.MyPrototypeService@268f106e
Prototype 2: com.example.quipoin.MyPrototypeService@6e9a5ed8- Different memory addresses
- New instance created each time
- Prototype confirmed
3. Web-Specific Scopes
These scopes only work in a Spring Web application (Spring MVC / Spring Boot Web).
A. Request Scope
Creates one bean per HTTP request.
@Component@Scope(value = WebApplicationContext.SCOPE_REQUEST)public class RequestBean {}Used for:
- Capturing request data
- Request-level state
B. Session Scope
Creates one bean per user session.
@Component@Scope(value = WebApplicationContext.SCOPE_SESSION)public class SessionBean {}Used for:
- User login storage
- Shopping cart
- Session metadata
C. Application Scope
Creates one bean per ServletContext (per web application).
Used for:
- App-wide configuration
- Caches
- Global objects
When Should You Use Which Scope?
| Scope | When to Use | Instance Count |
|---|---|---|
| Singleton | Always for stateless services | 1 per Application |
| Prototype | Temporary, stateful or custom objects | New each request |
| Request | Web request data | Per HTTP request |
| Session | User-specific data | Per user session |
| Application | Global app-level data | Per ServletContext |
Key Point
- Singleton = default and perfect for shared services
- Prototype creates new objects whenever needed
- Web scopes help manage request / session-based data
- To verify scope differece, you must run the application
- The memory address printed in logs is the easiest proof