Bean Scopes: Singleton vs Prototype vs Request vs Session
Fast recall
Quick revision
Core answer
ApplicationContext. Prototype — a new instance on every injection or getBean() call. Request and Session scopes (web-only) — one instance per HTTP request or session. The two production traps: singleton does not mean thread-safe (one instance shared across threads = race conditions on mutable state), and Spring does not call `@PreDestroy` on prototype beans (cleanup is the caller's responsibility). Injecting request-scoped beans into singletons requires a scoped proxy (@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)).Practical knowledge of scope selection and awareness of the 'scoped proxy' problem when injecting a short-lived bean into a singleton.
Assuming singleton means thread-safe, or not knowing that Spring does NOT manage the destruction lifecycle of prototype beans after creation.
Explain the scoped-proxy pattern (@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)) needed when injecting a request/session-scoped bean into a singleton.
Interview-ready guide
Interview answer
Spring's default scope is singleton — one instance per ApplicationContext, shared across all threads. Most developers never change this and assume it means safe. Two misconceptions cause real bugs.
Singleton
- One instance per container, shared across all threads — mutable state in a singleton bean is a race condition waiting to happen
- Full lifecycle: Spring calls
@PostConstructand@PreDestroy; the bean lives for the entire application lifetime
Prototype
- New instance every time the bean is injected or
getBean()is called — isolated, no sharing between threads - Spring creates but never destroys prototype beans;
@PreDestroyis never called; if the prototype holds a database connection or file handle, the calling code must close it
Request and Session scopes
- One instance per HTTP request or per HTTP session — correct for per-user or per-request state
- Injecting a request-scoped bean into a singleton is the most common scope trap: the singleton is created at startup before any request exists; Spring throws
BeanCreationException: no thread-bound request found - Fix:
@Scope(value="request", proxyMode=ScopedProxyMode.TARGET_CLASS)— Spring injects a CGLIB proxy; each method call resolves the real request-scoped bean from the current thread
Use singleton for stateless services (the default), prototype when you need isolated mutable state per use, request/session for web-specific state. Never store per-request state in a singleton field.
Bean Scopes: Singleton vs Prototype vs Request vs Session
Direct Answer
Spring scopes control how many instances of a bean exist and for how long. Singleton (the default) — one shared instance per ApplicationContext. Prototype — a new instance on every injection or getBean() call. Request and Session scopes (web-only) — one instance per HTTP request or session. The two production traps: singleton does not mean thread-safe (one instance shared across threads = race conditions on mutable state), and Spring does not call @PreDestroy on prototype beans (cleanup is the caller's responsibility). Injecting request-scoped beans into singletons requires a scoped proxy (@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)).
Common Mistakes & Pitfalls
Assuming singleton means thread-safe, or not knowing that Spring does NOT manage the destruction lifecycle of prototype beans after creation.
Check your understanding
Answer these without looking back at the article.
- How do you inject a prototype-scoped bean into a singleton without getting the same instance every time?
- Why doesn't Spring call @PreDestroy on prototype beans?
- What is ScopedProxyMode.TARGET_CLASS and when would you use it over INTERFACES?
- How does @RefreshScope work and what are its limitations?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.