Understanding Dependency Injection and IoC in Spring: From Direct Instantiation to Factory Pattern and Reflection
This article explains why dependency injection reduces coupling compared with direct object creation, walks through traditional instantiation, interface programming, factory methods, and reflection, and shows how Spring IoC combines these techniques to manage object lifecycles and improve code maintainability.
In many Java learning scenarios, beginners wonder why using dependency injection (DI) can lower coupling compared with directly creating objects with new . This article walks through the reasoning step by step.
1. Traditional object creation
Creating objects directly ties the client code to concrete classes:
WuliCar wuli = new WuliCar();
wuli.run();
BaomaCar baoma = new BaomaCar();
baoma.run();
ZhiShenJi zhi = new ZhiShenJi();
zhi.fly();If the business logic needs to replace a car with a helicopter, every occurrence of the concrete class must be changed, which is error‑prone and labor‑intensive.
2. Interface programming
Defining a common interface decouples the client from concrete implementations:
public interface Vehicle {
// Define a vehicle with a work method
void work();
}
public class Baoma implements Vehicle {
@Override
public void work() {
System.out.println("宝马跑起来");
}
}
public class ZhiShenJi implements Vehicle {
@Override
public void work() {
System.out.println("直升机飞起来");
}
}Now the client only depends on the Vehicle interface, but the creation code is still scattered.
3. Factory method
A factory class centralizes object creation:
class VehicleFactory {
VehicleFactory() {}
public static Vehicle getInstance(String type) {
Vehicle result = null;
if ("car".equals(type)) {
result = new Car();
}
if ("zhishenji".equals(type)) {
result = new ZhiShenJi();
}
return result;
}
}
Vehicle vehicle = VehicleFactory.getInstance("car");
vehicle.work();Adding a new vehicle type still requires modifying the factory, and the client must still specify the concrete type string.
4. Reflection
Using reflection (or configuration files) removes the hard‑coded type from the client code:
Vehicle vehicle = VehicleFactory.getInstance(readConfigFile());
vehicle.work();
// Desired type: zixingche
zixingche.work();Now the only place to change is the configuration, dramatically reducing coupling.
5. Spring IoC
Spring's Inversion of Control container combines the factory pattern and reflection to automatically create and wire objects, managing their lifecycle and dependencies without any explicit new statements in business code.
6. Summary
Dependency injection means the required objects are provided by a container rather than created manually, achieving loose coupling.
The caller only declares the component it needs; the container handles lookup, creation, and lifecycle.
Frameworks like Spring abstract object creation, allowing developers to focus on business logic.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.