Spring — IoC and beans
Spring is first and foremost an IoC container. Instead of your code creating its own dependencies with new, objects (called beans) are managed by the container: it reads bean definitions, instantiates them, wires them together, and holds them for the application's lifetime. Your class merely declares what it needs — the ApplicationContext does the rest.
Two questions grow out of this idea, asked on nearly every Spring interview: what inversion of control and dependency injection are — and how the container decides how many instances of a bean to create and how long to keep them (the scope). The second question almost always drags in a third: is the default singleton thread-safe (no). The breakdown is in the layers below.
Topic map
- Inversion of control and DI — the container, not your code, creates and wires objects; constructor injection versus field injection.
- Bean scopes —
singleton(the default),prototype,request/session; why a scope controls instance count, not thread-safety.
Common traps
| Mistake | Consequence |
|---|---|
Calling new on a dependency instead of injecting it | The object is outside the container: no beans, proxies, or configuration reach it |
Field injection via @Autowired instead of the constructor | The dependency cannot be final, is hidden, and breaks plain-new tests |
Assuming the default scope is prototype | The default is singleton — one shared instance per container |
| Keeping mutable state in a singleton bean | A data race: concurrent requests share the same instance |
| Expecting the container to synchronize beans for you | A scope controls instance count, not thread-safety |
Injecting a prototype into a singleton and expecting a fresh instance each time | The dependency is resolved once — when the singleton is created |
Interview relevance
Spring comes up on almost every Java backend interview, but the check is not annotation recall — it is your model of object ownership: who creates them, how many there are, and how long they live.
Typical checks:
- What inversion of control is and why DI is a special case of it.
- The trade-offs of constructor injection versus field injection.
- The
singleton/prototype/request/sessionscopes and what each one sets. - Whether the default
singletonis thread-safe and what to do about it. - What happens when a
prototypebean is injected into a singleton.
Common wrong answer: "a singleton is thread-safe because there is only one." That single instance is exactly the problem: every thread shares it, so any mutable field becomes shared state. A scope controls instance count, not synchronization; safety comes from being stateless or from explicit synchronization.