Dependency Injection in Java Explained with Examples | Beginner to Advanced Guide
Reading Time: 14–17 minutes
Dependency Injection (DI) is a design principle and design pattern used to achieve loose coupling between classes. Instead of a class creating its own dependencies, the required dependencies are provided from outside.
Dependency Injection is widely used in modern Java applications, especially in frameworks like Spring Boot. It improves testability, flexibility, and maintainability of code.
This tutorial explains Dependency Injection from beginner to advanced level with simple examples, step-by-step implementation, and real-world understanding.
What is Dependency Injection
Dependency Injection is a technique where an object receives its dependencies from an external source instead of creating them internally.
Simple definition:
Do not create dependencies inside a class. Inject them from outside.
Understanding Dependency and Injection
What is Dependency
A dependency is an object that another object requires to perform its task.
Example: Car depends on Engine.
What is Injection
Injection means providing the required dependency from outside the class.
Why Do We Need Dependency Injection
Let us understand the problem first.
Problem Without Dependency Injection
Suppose a service directly creates its dependency.
package com.codekatha;
class MySQLDatabase {
public void connect() {
System.out.println("Connected to MySQL database");
}
}
class UserService {
private MySQLDatabase database = new MySQLDatabase();
public void saveUser() {
database.connect();
System.out.println("User saved");
}
}
Problems in This Approach
Tight coupling between classes
Difficult to switch database implementation
Hard to test
Violates Dependency Inversion Principle
If we want PostgreSQL instead of MySQL, we must modify UserService.
Solution – Dependency Injection
Instead of creating the dependency inside the class, we pass it from outside.
This reduces coupling and increases flexibility.
Key Idea Behind Dependency Injection
Remove object creation responsibility
Provide dependencies externally
Promote loose coupling
Improve testability
Implementing Dependency Injection Step-by-Step
Step 1 – Create Interface for Dependency
package com.codekatha;
interface Database {
void connect();
}
Step 2 – Create Concrete Implementations
package com.codekatha;
class MySQLDatabase implements Database {
public void connect() {
System.out.println("Connected to MySQL database");
}
}
class PostgreSQLDatabase implements Database {
public void connect() {
System.out.println("Connected to PostgreSQL database");
}
}
Step 3 – Inject Dependency into Class
package com.codekatha;
class UserService {
private Database database;
public UserService(Database database) {
this.database = database;
}
public void saveUser() {
database.connect();
System.out.println("User saved");
}
}
Step 4 – Client Code
package com.codekatha;
class DIDemo {
public static void main(String[] args) {
Database database = new MySQLDatabase();
UserService service = new UserService(database);
service.saveUser();
}
}
Now we can easily change the database without modifying UserService.
What We Achieved Using Dependency Injection
Loose coupling between classes
Easy to change implementations
Better testability
Follows Dependency Inversion Principle
Types of Dependency Injection
Constructor Injection (Recommended)
Dependencies are provided through constructor.
Ensures required dependency
Immutable design possible
Most preferred approach
Setter Injection
Dependencies are provided using setter methods.
public void setDatabase(Database database) {
this.database = database;
}
Useful for optional dependencies.
Field Injection
Dependency is injected directly into fields (commonly used in Spring).
This approach is not recommended in plain Java due to testing issues.
Dependency Injection vs Factory Pattern
Factory creates objects.
Dependency Injection provides objects.
Factory handles creation logic, while DI handles dependency management.
Dependency Injection vs Service Locator
Dependency Injection → Dependencies provided externally.
Service Locator → Class requests dependencies itself.
Advantages of Dependency Injection
Reduces tight coupling
Improves maintainability
Enhances testability
Supports flexible design
Follows SOLID principles
Disadvantages of Dependency Injection
More configuration required
Slightly complex setup
Harder to understand for beginners
When Should You Use Dependency Injection
When building large applications
When multiple implementations exist
When writing testable code
When following SOLID principles
Real-World Usage of Dependency Injection
Spring Framework
Spring Boot applications
JUnit testing with mocks
Enterprise Java applications
Dependency Injection in Spring Framework
Spring provides automatic dependency injection using annotations.
@Autowired
private UserService userService;
The framework automatically provides the dependency.
Common Interview Questions on Dependency Injection
What is Dependency Injection?
Constructor vs Setter injection?
DI vs Factory pattern?
How DI supports loose coupling?
Simple Summary
Dependency Injection provides dependencies externally.
Reduces tight coupling.
Improves flexibility and testability.
Commonly used in Spring framework.
Conclusion
Dependency Injection is a powerful design principle that promotes flexible and maintainable application design. It removes dependency creation responsibility and allows systems to evolve easily.
Comments
Post a Comment