Dependency Inversion is a SOLID principle that says depend on abstractions, not concrete classes. Inversion of Control means shifting object creation and lifecycle management to a framework/container. Dependency Injection is the technique used by IoC containers to inject dependencies into classes (via constructor, setter, or field).
1. Dependency Inversion Principle (DIP)
Type: Design Principle (SOLID)
High-level modules should NOT depend on low-level modules. Both should depend on abstractions.
In simple words:
Depend on interfaces, not concrete classes.
Without DIP
class MySQLDatabase {
void save(String data) {
System.out.println("Saved to MySQL");
}
}
class UserService {
private MySQLDatabase db = new MySQLDatabase(); // Tight coupling
void saveUser(String user) {
db. save(user);
}
}
Problem:
- UserService tightly coupled to MySQL
- Cannot switch to MongoDB / PostgreSQL easily
With DIP:
interface Database {
void save(String data);
}
class MySQLDatabase implements Database {
public void save(String data) {
System.out.println("Saved to MySQL");
}
}
class UserService {
private Database db;
UserService(Database db) { // Depends on abstraction
this.db = db;
}
void saveUser(String user) {
db.save(user);
}
}
- Now we can plug any DB implementation.
2. Inversion of Control (IoC)
Type: Design Pattern / Architecture Principle
Control of object creation & lifecycle is inverted (shifted) from the application code to a container/framework.
Instead of YOU creating objects → Framework creates & manages them.
Without IoC
UserService service = new UserService(new MySQLDatabase());
You control creation.
With IoC (Spring Example)
@ Service
class UserService {
private Database db;
public UserService(Database db) {
this.db = db;
}
}
Spring Container does:
- Create Database bean
- Create UserService bean
- Inject dependency
You don’t control creation anymore.
3. Dependency Injection (DI)
Type: Implementation Technique of IoC
Dependencies are injected into a class rather than created inside it.
DI is HOW IoC is achieved.
Types of DI
1. Constructor Injection (Recommended)
class UserService {
private Database db;
UserService(Database db) {
this.db = db;
}
}
2. Setter Injection
class UserService {
private Database db;
void setDatabase(Database db) {
this.db = db;
}
}
3. Field Injection (Spring)
@ Autowired
private Database db;