Why this matters
- Injecting request-specific state into a singleton bean is a common bug that causes data leaks between BookStore customers.
- Understanding lifecycle callbacks lets you open resources at startup and close them on shutdown cleanly.
- Scope questions appear in interviews because the wrong scope silently corrupts concurrent requests.
Singleton scope (default)
@Service // scope defaults to singleton
public class BookService { ... }
One instance per ApplicationContext. Every HTTP request shares the same BookService. This is correct for stateless services that delegate to repositories.
Never store request data in a singleton field:
@Service
public class BookService {
private String currentUser; // BUG: shared across all requests!
}
Prototype scope
@Component
@Scope("prototype")
public class SearchCriteriaBuilder {
private List<String> filters = new ArrayList<>();
// each injection gets a fresh instance
}
A new instance every time the bean is requested. Useful for builder objects or per-operation state. Spring does not manage prototype destruction — you own cleanup.
Web scopes
Scopes for web applications
- request — One instance per HTTP request; ideal for request-scoped DTOs.
- session — One instance per HTTP session; shopping cart state in BookStore.
- application — One instance per
ServletContext; rarely used directly.
Enable web scopes with @EnableWebMvc or by using spring-boot-starter-web (already active in BookStore).
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestContext {
private String correlationId;
}
proxyMode is required when injecting a shorter-lived bean into a singleton — Spring creates a proxy that resolves the real instance per request.
Lifecycle callbacks
Beans can hook into creation and destruction:
@Service
public class InventorySyncService {
@PostConstruct
public void warmCache() {
// runs after dependency injection completes
log.info("Inventory cache warmed");
}
@PreDestroy
public void flushPending() {
// runs before context shutdown
log.info("Flushing pending inventory updates");
}
}
Alternative: implement InitializingBean and DisposableBean interfaces — functionally identical but less idiomatic.
Startup ordering with @DependsOn
When BookService must start after ReferenceDataLoader:
@Service
@DependsOn("referenceDataLoader")
public class BookService { ... }
@Component
public class ReferenceDataLoader {
@PostConstruct
public void load() {
// populate genre lookup table
}
}
@DependsOn controls creation order without constructor coupling.
Lazy initialisation
@Service
@Lazy
public class ReportGenerator {
public ReportGenerator(ExpensiveDataSource ds) { ... }
}
Bean creation deferred until first use. Breaks circular dependencies but delays failure detection. Use sparingly in BookStore — fail fast at startup is usually better.
Scope in practice for BookStore
| Component | Recommended scope | Reason |
|---|---|---|
| BookService | singleton | Stateless business logic |
| BookRepository | singleton | Backed by connection pool |
| ShoppingCart | session | Per-user cart state |
| RequestIdHolder | request | Per-request correlation ID |
BookService
Recommended scopesingletonReasonStateless business logicBookRepository
Recommended scopesingletonReasonBacked by connection poolShoppingCart
Recommended scopesessionReasonPer-user cart stateRequestIdHolder
Recommended scoperequestReasonPer-request correlation ID
Observing bean creation
Enable debug logging to see instantiation order:
logging:
level:
org.springframework.beans.factory: DEBUG
Each Creating instance of bean log line shows the container's creation sequence.
Quick recall
Everything you need if you only revisit this box.
- Default scope is singleton — one shared instance for the entire application.
- Never store per-request state in singleton fields.
- Request and session scopes tie bean lifetime to HTTP lifecycle.
- Use
proxyMode = TARGET_CLASSwhen injecting web-scoped beans into singletons. @PostConstructruns after injection;@PreDestroyruns before shutdown.@DependsOncontrols bean creation order without constructor dependencies.
Test yourself
Answer these before moving on — recall is what makes it stick.