(Reference: Spring Docs - IoC Container)
🔹 What is IoC (Inversion of Control)?
💡 IoC is a design principle where the control of object creation and management is shifted from the developer to the framework (Spring).
🛠️ Before IoC: Traditional Object Creation (Manual Control)
public class PirateShip {
private Captain captain;
public PirateShip() {
this.captain = new Captain(); // MANUAL CREATION
}
}
❌ Problem: The class creates its own dependencies, leading to tight coupling (harder to test & maintain).
⚡ IoC in Action: Spring Controls Object Creation
With IoC, Spring is responsible for creating and injecting dependencies instead of the developer doing it manually.
@Component
public class Captain {
public String getCommand() {
return "Set sail, Matey! ☠️";
}
}
@Component
public class PirateShip {
private final Captain captain;
@Autowired
public PirateShip(Captain captain) {
this.captain = captain;
}
public String sail() {
return captain.getCommand();
}
}
💡 Spring injects the Captain
instance into PirateShip
automatically.
🔹 What is Dependency Injection (DI)?
💡 Dependency Injection (DI) is how Spring implements IoC—it automatically provides the required dependencies to objects.
✅ No new
keyword needed.
✅ Objects are loosely coupled (easier to test & modify).
✅ Easier configuration via annotations or XML.
📌 Types of Dependency Injection in Spring
(Reference: Spring Docs - Dependency Injection)
1️⃣ Constructor Injection (Recommended)
🚀 Inject dependencies via constructor (Best Practice).
@Component
public class PirateShip {
private final Captain captain;
@Autowired
public PirateShip(Captain captain) { // Injecting dependency via constructor
this.captain = captain;
}
}
✅ Best for mandatory dependencies.
✅ Ensures immutability (final fields).
2️⃣ Setter Injection
🚀 Inject dependencies via setter methods.
@Component
public class PirateShip {
private Captain captain;
@Autowired
public void setCaptain(Captain captain) { // Setter-based injection
this.captain = captain;
}
}
✅ Good for optional dependencies.
❌ Can lead to mutable objects (less safe).
3️⃣ Field Injection (NOT Recommended)
⚠️ Directly injecting fields using @Autowired
.
@Component
public class PirateShip {
@Autowired
private Captain captain;
}
❌ Considered a bad practice because:
- Harder to test (no way to pass a mock in tests).
- Breaks immutability (makes class state changeable).
🔥 Best Practice: Use Constructor Injection whenever possible!
📌 Hands-On Project: IoC & DI in Action
Step 1: Create a Spring Boot Project
1️⃣ Go to Spring Initializr
2️⃣ Select:
- Spring Boot Version: Latest stable
- Dependencies: Spring Web
- Packaging: Jar 3️⃣ Click Generate and extract the zip file.
Step 2: Define Components
📌 Create a Captain
component:
package com.example.springdi;
import org.springframework.stereotype.Component;
@Component
public class Captain {
public String giveOrder() {
return "All hands on deck, Matey! ☠️";
}
}
📌 Create a PirateShip
component that depends on Captain
:
package com.example.springdi;
import org.springframework.stereotype.Component;
@Component
public class PirateShip {
private final Captain captain;
public PirateShip(Captain captain) {
this.captain = captain;
}
public String sail() {
return captain.giveOrder();
}
}
Step 3: Create a REST Controller
📌 Expose the PirateShip
behavior via an API:
package com.example.springdi.controller;
import com.example.springdi.PirateShip;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/pirates")
public class PirateController {
private final PirateShip pirateShip;
public PirateController(PirateShip pirateShip) {
this.pirateShip = pirateShip;
}
@GetMapping("/sail")
public String sail() {
return pirateShip.sail();
}
}
Step 4: Run the Application
💡 Run the app using:
mvn spring-boot:run
or
./mvnw spring-boot:run
🌐 Visit: http://localhost:8080/pirates/sail
🎉 You should see:
All hands on deck, Matey! ☠️
📌 Summary
✅ IoC = Spring takes control of object creation and lifecycle.
✅ DI = Injecting dependencies instead of creating them manually.
✅ Constructor Injection is best practice!
✅ We built a real Spring Boot app demonstrating DI!
📌 Topics Covered in This Section
📜 IoC & Dependency Injection (✔️ Covered)
- What is IoC? (Spring manages object creation, inversion of control).
- What is DI? (Spring injects dependencies, reducing coupling).
- Spring’s IoC container (ApplicationContext & BeanFactory).
- Types of DI: Constructor, Setter, Field Injection (Pros/Cons).
- Best Practices: Constructor Injection > Setter Injection > Field Injection.
🛠️ Spring Boot & IoC (✔️ Covered)
- Auto-Configuration & @Component Scanning.
- @Autowired behavior and limitations.
- How IoC integrates into a Spring Boot project.
🔥 Key Takeaways You Need to Remember for the Exam:
✅ Spring’s IoC container creates, configures, and manages objects (beans).
✅ DI eliminates the need for new keyword by injecting dependencies.
✅ Spring Boot automatically registers components using @ComponentScan.
✅ @Autowired is used for injection but Constructor Injection is best practice.