Backend Development 8 min read

Understanding Dependency Injection and Spring IoC: From Direct Instantiation to Factory and Reflection

This article explains why dependency injection reduces coupling compared to direct object creation, demonstrates traditional instantiation, interface programming, factory method, and reflection techniques, and shows how Spring IoC combines these concepts to manage object lifecycles in Java backend development.

Top Architect
Top Architect
Top Architect
Understanding Dependency Injection and Spring IoC: From Direct Instantiation to Factory and Reflection

Hello everyone, I am a senior architect.

Question: In learning the Spring framework, why does dependency injection lower code coupling compared to creating objects with new ?

1. Traditional object creation

Usually we create objects directly:

WuliCar wuli = new WuliCar();
wuli.run();

When the business needs change (e.g., replace a Wuling car with a BMW or a helicopter), every place where the concrete class is instantiated must be modified, leading to massive code changes.

2. Interface programming

Define a common interface to decouple the client from concrete implementations:

public interface vehicle {
    void work();
}

Implement the interface for different vehicles:

public class Baoma implements vehicle {
    @Override
    public void work() {
        System.out.println("BMW runs");
    }
}

public class ZhiShenJi implements vehicle {
    @Override
    public void work() {
        System.out.println("Helicopter flies");
    }
}

Now the client only depends on the vehicle interface; switching implementations only requires changing the instantiation point.

3. Factory method

Encapsulate object creation in a factory class:

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;
    }
}

Clients request a vehicle by name, e.g., Vehicle vehicle = VehicleFactory.getInstance("zixingche"); vehicle.work(); , so only the factory needs to know the concrete class.

4. Reflection

Further improve flexibility by reading the desired type from a configuration file and creating the instance via reflection:

Vehicle vehicle = VehicleFactory.getInstance(readFromConfigFile);
vehicle.work();
// Desired: zixingche
// After change: zixingche.work();

This way, changing the implementation requires editing only the configuration file, not the source code.

5. Spring IoC

Spring's Inversion of Control container implements the factory‑plus‑reflection approach automatically, managing object lifecycles and wiring dependencies, thus achieving low coupling without manual factory code.

6. Summary

Dependency injection means the required objects are provided by a container rather than created manually, promoting orthogonal (loosely‑coupled) design.

The caller declares a component and receives it; the container handles lookup, creation, and lifecycle management.

Developers can focus on business logic while the framework manages object creation and destruction.

JavaBackend DevelopmentReflectionIoCSpringdependency injectionFactory Pattern
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.