Java Series #14: Spring IoC, Beans & Spring MVC
Spring IoC, Beans & Spring MVC — Explained Without the Noise

I am a Full-stack dev turning ideas into sleek, functional experiences 🚀. I am passionate about AI, intuitive UI/UX, and crafting user-friendly platforms . I am always curious – from building websites to diving into machine learning and under the hood workings ✨. Next.js, Node.js, MongoDB, and Tailwind are my daily tools. I am here to share dev experiments, lessons learned, and the occasional late-night code breakthroughs. Always evolving, always building.
Spring feels confusing only when concepts are learned in isolation.
This article connects IoC, containers, beans, DI, lifecycle, scopes, and finally shows how Spring MVC fits on top of all this — in one clean flow.
1. The Core Problem Spring Solves
Without Spring, you write:
Engine engine = new Engine();
Car car = new Car(engine);
You are responsible for:
creating objects
wiring dependencies
managing lifecycle
This leads to tight coupling and hard-to-maintain code.
2. IoC (Inversion of Control): The Big Idea
You don’t create objects. Spring does.
Spring:
creates objects (beans)
injects dependencies
manages lifecycle
📌 IoC is the principle
📌 Container is the implementation
📌 Bean is the object Spring manages
3. Bean Container vs IoC Container
IoC container → concept (who controls object creation?)
Bean container → actual Spring container implementation
In Spring, these are practically the same thing.
4. Types of Spring Containers
1️. BeanFactory (Basic)
Oldest container
Lazy initialization
Basic DI support
BeanFactory factory = new XmlBeanFactory(resource);
✅ Lightweight
❌ No events, no i18n, no auto post-processing
Used rarely today.
2️. ApplicationContext (Recommended)
BeanFactory + enterprise features
Adds:
event propagation
internationalization (i18n)
automatic BeanPostProcessor execution
AOP integration
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
📌 Used in almost all modern Spring apps
5. Dependency Injection Types
1️. Constructor Injection (Best Practice)
@Component
class Car {
private final Engine engine;
@Autowired
public Car(Engine engine) {
this.engine = engine;
}
}
mandatory dependencies
immutable
test-friendly
2️. Setter Injection
@Autowired
public void setEngine(Engine engine) {
this.engine = engine;
}
optional dependencies
mutable
3️. Field Injection (Avoid)
@Autowired
private Engine engine;
hard to test
hides dependencies
6. Autowiring & @Qualifier
Spring injects dependencies by type first.
Problem: Multiple beans of same type
@Component class PetrolEngine implements Engine {}
@Component class DieselEngine implements Engine {}
@Autowired
Engine engine; // ambiguity error
Solution: @Qualifier
@Autowired
@Qualifier("dieselEngine")
private Engine engine;
Key points:
resolves ambiguity
works with constructor, setter, field
injects specific bean by name
no match → exception (or
nullif optional)
7. Bean Lifecycle (Simplified)
Container starts
→ Bean created
→ Dependencies injected
→ Initialization
→ Bean ready
→ Container shuts down
→ Bean destroyed
Lifecycle Hooks
Annotations (preferred):
@PostConstruct
void init() {}
@PreDestroy
void destroy() {}
Other options:
XML
init-method/destroy-methodInterfaces (
InitializingBean,DisposableBean)
8. BeanPostProcessor vs BeanFactoryPostProcessor
BeanFactoryPostProcessor
runs before beans are created
modifies bean definitions
BeanPostProcessor
runs after bean creation
modifies actual bean instances
used in AOP, proxies, security
📌 ApplicationContext handles both automatically.
9. Bean Scopes
| Scope | Meaning |
| singleton | one instance per container (default) |
| prototype | new instance each request |
| request | one per HTTP request |
| session | one per HTTP session |
| globalSession | legacy, rarely used |
Where Spring MVC Fits ?
Up to now, everything works even without web.
So how do HTTP requests enter the picture?
Spring Core vs Spring MVC
Spring Core
IoC container
beans
DI
lifecycle
scopes
Spring MVC
HTTP handling
controllers
URL mapping
view resolution
📌 Spring MVC runs on top of Spring Core
Controllers are just beans.
DispatcherServlet: The Heart of Spring MVC
Spring MVC answers three questions:
Who receives HTTP requests?
Which controller handles them?
Which view should be returned?
Answer to #1:
DispatcherServlet
Request flow:
Browser
→ DispatcherServlet
→ Controller (bean)
→ Service (bean)
→ Repository (bean)
→ Database
Nothing bypasses IoC.
Controllers Are Normal Beans
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
Truth:
@Controller=@Componentlifecycle rules apply
DI works the same way
ViewResolver
Controller returns:
return "home";
ViewResolver converts it to:
/WEB-INF/views/home.jsp
This is configuration, not controller logic.
Spring Boot Reality Check
If you use Spring Boot:
no
web.xmlno manual DispatcherServlet config
no XML
Spring Boot auto-configures:
DispatcherServlet
component scanning
MVC setup
You focus on business logic only.
Final Mental Model
ApplicationContext
→ creates beans
→ injects dependencies
→ manages lifecycle
→ applies scopes
↓
Spring MVC
→ DispatcherServlet
→ Controller beans
→ HTTP handling
Spring doesn’t remove complexity it centralizes and manages it for you.
Spring MVC is a web framework built on top of Spring’s IoC container, where controllers are regular beans managed through dependency injection, lifecycle control, and scopes.



