(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.
Top comments (0)