Lesson 4 · Spring Core

Bean Scopes

How long a bean lives and how many instances exist — plus the two scope gotchas that show up almost every exam.

What you'll be tested on The default scope, what singleton actually means, how prototype differs (and the surprising thing Spring won't do for prototypes), the web scopes, and — the tricky one — what happens when you inject a short-lived bean into a long-lived one.

The scope catalogue

ScopeInstancesNotes
singletonOne per containerDefault. Created eagerly at startup, shared everywhere.
prototypeA new one every time it's requested/injectedSpring builds it then lets go — see the destruction gotcha below.
requestOne per HTTP requestWeb scopes — need a web-aware ApplicationContext.
sessionOne per HTTP session
applicationOne per ServletContext
websocketOne per WebSocket session
"Singleton" ≠ one per JVM A singleton is one instance per Spring container, not the Gang-of-Four "one per classloader". Two ApplicationContexts → two instances of the same singleton bean. Classic distractor.

Declaring a scope

@Component
@Scope("prototype")                 // or @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Report { ... }

@Bean
@Scope("prototype")
public Report report() { return new Report(); }

The prototype destruction gotcha

For a prototype bean, Spring instantiates it, wires it, runs @PostConstruct… and then hands it over and forgets about it. The container does not track prototype instances, so:

Spring does NOT call destroy callbacks on prototype beans No @PreDestroy, no DisposableBean.destroy(), no custom destroy-method is invoked by the container for a prototype. Releasing resources is the caller's responsibility. (Init callbacks like @PostConstruct do still run.)

Injecting a short-lived bean into a singleton

This is the highest-value scope question. A singleton is created once. So if you inject a prototype (or request) bean into it the ordinary way, the singleton grabs one instance at creation time and reuses that same one forever — defeating the point of the shorter scope.

@Service                          // singleton — created ONCE
public class Dashboard {
  @Autowired Report report;         // prototype... but frozen to ONE instance here
}

Four correct fixes — each gives the singleton a fresh instance per use instead of one forever:

Rule of thumb Injecting a bean of equal or longer lifetime? Plain @Autowired is fine. Injecting a shorter-lived bean into a longer-lived one? You need a proxy or a provider.
Primary source — read this
Spring Framework 5.3 — Core: Bean Scopes

Read "The Singleton Scope", "The Prototype Scope" (note the destruction paragraph), and "Scoped Beans as Dependencies" (the proxy solution above).

Check yourself

The prototype-destruction fact and the scoped-into-singleton fix are the two to nail. Options shuffle on every load.

Then drill the book Container section: Q2 (@Lazy), Q13 (prototype), Q28 (default scope), Q30 (request scope), Q36 (which scopes exist). Then re-run the Container Drill.
I'm your teacher — ask me anything. The scoped-proxy mechanism is worth seeing in motion — ask me to trace how a proxy hands the singleton a fresh request bean. Say "continue" for Lesson 5 — Properties, Profiles & SpEL.
← Lesson 3 · Component Scanning Lesson 5 · Properties, Profiles & SpEL → (coming next)