What Scopes Exist in Spring?
4. Scoped Proxy - for injecting narrow scopes into wider ones 5. ObjectProvider - alternative to Scoped Proxy 6. RefreshScope - for dynamic configuration
Junior Level
Scope defines how many instances of a bean Spring creates.
| Scope | How many instances |
|---|---|
| Singleton | One for the entire application (default) |
| Prototype | New on each request |
| Request | One per HTTP request |
| Session | One per HTTP session |
@Service // Singleton
public class UserService { }
@Scope("prototype")
@Service
public class Report { } // New each time
Middle Level
Standard Scopes
Singleton:
// One instance per ApplicationContext
// All threads use the same object
// -> Must be Stateless!
Prototype:
// New on each getBean()
// Spring does NOT call @PreDestroy!
// -> You clean resources yourself
Web Scopes
@Scope("request") // One per HTTP request
@Scope("session") // One per user session
@Scope("application") // One per ServletContext
Custom Scopes
// Your own scope!
context.getBeanFactory().registerScope("thread", new ThreadScope());
// ThreadScope - custom implementation of org.springframework.beans.factory.config.Scope interface.
// Stores beans in ThreadLocal. Not built into standard Spring - this is an example.
// Spring Cloud: Refresh Scope
// -> Bean is recreated when configuration is updated
Problem: Narrow Scope in Singleton
// Request bean created once at Singleton startup
@Service
public class SingletonService {
@Autowired RequestBean requestBean; // Stuck with the first one!
}
// Scoped Proxy
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean public RequestBean requestBean() { }
// ObjectProvider
@Autowired ObjectProvider<RequestBean> provider;
RequestBean bean = provider.getObject(); // Actual!
Senior Level
ScopedProxyMode
TARGET_CLASS (CGLIB):
-> Creates proxy subclass
-> Proxy -> RequestContextHolder -> actual bean
INTERFACES (JDK):
-> Proxies only interfaces
NO:
-> No proxy -> problem with Singleton
Under the Hood: Where They Are Stored
Singleton -> DefaultSingletonBeanRegistry (ConcurrentHashMap)
Request -> stored in HttpServletRequest attributes, accessed via RequestContextHolder (ThreadLocal)
Session -> SessionAttributes
Prototype -> Not stored, created each time
Refresh Scope (Spring Cloud)
@RefreshScope
@ConfigurationProperties("my.config")
public class MyConfig { }
// On update via Spring Cloud Bus:
// -> Proxy is invalidated
// -> On next request, recreated with new data
Production Experience
Real scenario: Session scope in microservice
Session scope -> ThreadLocal -> works on one node
-> Load Balancer -> request to another node -> Session lost!
Solution: Spring Session + Redis
-> Session stored in Redis -> available on all nodes
Best Practices
- Singleton - for services and repositories
- Prototype - for heavy stateful objects
- Web scopes - for user data
- Scoped Proxy - for injecting narrow scopes into wider ones
- ObjectProvider - alternative to Scoped Proxy
- RefreshScope - for dynamic configuration
Summary for Senior
- Singleton = one per ApplicationContext
- Prototype = new each time, @PreDestroy does NOT work
- Request/Session = web scope via ThreadLocal
- Scoped Proxy = proxy -> RequestContextHolder
- RefreshScope = recreation on config update
- Custom Scope = your own lifecycle
Interview Cheat Sheet
Must know:
- 4 standard scopes: Singleton (default), Prototype, Request, Session
- Singleton = one instance per ApplicationContext, Prototype = new on each request
- Web scopes (Request/Session) stored via ThreadLocal
- ScopedProxyMode (TARGET_CLASS/CGLIB, INTERFACES/JDK, NO) solves the problem of injecting narrow scopes into wider ones
- @PreDestroy is NOT called for Prototype - clean resources manually
- ObjectProvider - alternative to Scoped Proxy for Prototype/Request in Singleton
- RefreshScope (Spring Cloud) - bean recreation on configuration update
Common follow-up questions:
- How to inject Request scope into Singleton? -> Scoped Proxy (
proxyMode = TARGET_CLASS) or ObjectProvider - What happens if a Prototype bean holds resources? -> Leak, Spring will not call @PreDestroy, need to clean manually via try-finally
- Where does Spring store Singleton beans? -> DefaultSingletonBeanRegistry (ConcurrentHashMap)
- What does RefreshScope do? -> Invalidates proxy, recreates bean with new data on next request
Red flags (DO NOT say):
- “Prototype calls @PreDestroy” - does not call
- “Request scope is stored in Spring cache” - stored in HttpServletRequest attributes
- “Singleton is created on each access” - created once
- “Custom Scope is built into Spring” - you need to write your own Scope interface implementation
Related topics:
- [[12. Difference between singleton and prototype scope]]
- [[13. What is a proxy in Spring]]
- [[14. When does Spring create a proxy]]
- [[16. What is aspect advice pointcut join point]]