Dependency Injection (DI) is a design pattern where objects are provided with their dependencies instead of creating them directly.
It’s like saying:
“Hey, I don’t want to build this thing myself—just give me a ready-made one that I can use.”

🧠 Why Is It Important?
Without DI:
1 2 3 4 5 |
public class PaymentService { private UserRepository repo = new UserRepository(); // tightly coupled } |
With DI:
1 2 3 4 5 6 7 8 9 10 |
public class PaymentService { private final UserRepository repo; public PaymentService(UserRepository repo) { this.repo = repo; // loosely coupled, easier to test and replace } } |
✅ Benefits of DI:
- Cleaner code
- Better testability (you can mock dependencies)
- Encourages separation of concerns
- Makes code easier to manage and scale
🌱 How Dependency Injection in Spring Boot works
Spring Boot automatically injects beans using:
@Autowired
- Constructor injection
- Field injection
- Setter injection (less common)
Spring does this by:
- Scanning your classes for annotations like
@Component
,@Service
,@Repository
, etc. - Creating instances of these classes (called beans)
- Injecting them into other beans where required
🛠️ 1. Using @Component
to Define a Bean
Let’s say you have a simple service class:
1 2 3 4 5 6 7 8 9 |
@Component public class EmailService { public void sendEmail(String message) { System.out.println("Sending email: " + message); } } |
Now Spring knows to manage EmailService
as a bean.
🔁 2. Injecting a Dependency Using @Autowired
1 2 3 4 5 6 7 8 9 10 11 12 |
@Service public class NotificationService { @Autowired private EmailService emailService; public void notifyUser() { emailService.sendEmail("Welcome to Spring Boot!"); } } |
Here, Spring automatically injects an instance of EmailService
into NotificationService
.
💡 Best Practice: Constructor Injection
Instead of using @Autowired
on fields, use constructor injection:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Service public class NotificationService { private final EmailService emailService; public NotificationService(EmailService emailService) { this.emailService = emailService; } public void notifyUser() { emailService.sendEmail("Welcome to Spring Boot!"); } } |
✅ Advantages:
- Easier to test
- Makes immutability possible
- Encouraged by modern Spring practices
📘 Note: Since Spring 4.3+, if a class has only one constructor, Spring automatically injects dependencies — no need for @Autowired
.
💾 Example: Full Working Application
1 2 3 4 5 6 7 8 |
@SpringBootApplication public class DiDemoApplication { public static void main(String[] args) { SpringApplication.run(DiDemoApplication.class, args); } } |
EmailService.java
1 2 3 4 5 6 7 8 |
@Component public class EmailService { public void sendEmail(String message) { System.out.println("Email Sent: " + message); } } |
NotificationService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Service public class NotificationService { private final EmailService emailService; public NotificationService(EmailService emailService) { this.emailService = emailService; } public void notify() { emailService.sendEmail("Dependency Injection rocks!"); } } |
MyController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@RestController public class MyController { private final NotificationService notificationService; public MyController(NotificationService notificationService) { this.notificationService = notificationService; } @GetMapping("/send") public String sendNotification() { notificationService.notify(); return "Notification Sent!"; } } |
Visit: http://localhost:8080/send
✅ You should see:
1 2 3 |
Email Sent: Dependency Injection rocks! |
🔐 What Happens Behind the Scenes?
- Spring Boot starts and scans your classes (
@ComponentScan
) - It detects all
@Component
,@Service
,@Repository
, etc. - It creates and manages their instances (beans)
- It injects dependencies where required using reflection
🚫 Common Mistakes to Avoid
Mistake | Issue |
---|---|
Forgetting to annotate a class | Spring won’t recognize it as a bean |
Using field injection without @Autowired | Dependency will be null |
Trying to inject a bean that’s not scanned | Injection fails with NoSuchBeanDefinitionException |
Circular dependencies | Can lead to startup errors |
📘 FAQ
❓ Do I always need @Autowired
?
Not if you’re using constructor injection and the class has only one constructor. Spring will inject automatically.
❓ Can I inject one service into multiple components?
Yes! Spring manages beans as singletons by default (unless specified otherwise), so you can reuse them.
❓ What if I have multiple implementations of a dependency?
Use @Qualifier
to specify which one to inject.
1 2 3 4 |
@Autowired @Qualifier("smsService") private NotificationService service; |
📚 External References
✅ Summary
Concept | Description |
---|---|
DI (Dependency Injection) | Providing dependencies from outside |
@Component | Marks a class as a Spring bean |
@Autowired | Injects a dependency |
Constructor Injection | Recommended, testable, and cleaner |
Spring Container | Manages beans and performs the injection |
Spring Boot makes dependency injection effortless, letting you focus on your logic while it wires up everything behind the scenes.