DEV Community

realNameHidden
realNameHidden

Posted on

What Is Dependency Injection and How Is It Implemented in Spring?

Learn what Dependency Injection in Spring is, why it matters in Java programming, and how to implement it with simple examples.


Introduction

Imagine you buy a new TV, and every time it breaks, you’re forced to repair it yourself because all components are tightly welded together. Frustrating, right? Now imagine instead that each part can be replaced independently—much easier to maintain.

This is exactly the problem Dependency Injection (DI) solves in Java programming.

When beginners write Java code, classes often create their own dependencies. This makes applications hard to test, hard to change, and tightly coupled. Spring solves this elegantly using Dependency Injection, one of its core concepts.

In this blog, you’ll learn what Dependency Injection is, why it’s important, and how Spring implements it using simple, real-world analogies and clean Java 21 examples. By the end, you’ll clearly understand why DI is considered a foundation of modern Java development.


Core Concepts

What Is Dependency Injection?

At a simple level, Dependency Injection means giving an object what it needs, instead of the object creating it itself.

Let’s use a real-world analogy.

👉 Analogy: Mobile Charger

Your phone doesn’t manufacture its own charger. You inject the charger into the phone when needed. This allows:

  • Different chargers
  • Easy replacement
  • Better flexibility

In Java, a dependency is usually another class that your class needs to work.


Without Dependency Injection (Tightly Coupled Code)

public class Car {
    private Engine engine = new Engine(); // tightly coupled
}
Enter fullscreen mode Exit fullscreen mode

Problems:

  • You can’t change the engine easily
  • Hard to test
  • Code is rigid With Dependency Injection (Loosely Coupled Code)
public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }
}

Enter fullscreen mode Exit fullscreen mode

Now the Engine is injected, not created internally.

How Spring Implements Dependency Injection

Spring uses a principle called Inversion of Control (IoC).

  • You define what objects you need
  • Spring decides how and when to create them
  • Spring injects dependencies automatically Spring supports DI using:
  1. Constructor Injection (recommended)
  2. Setter Injection
  3. Field Injection (not recommended)

Benefits of Dependency Injection in Spring

  • Loose coupling
  • Easier testing (mocking)
  • Better maintainability
  • Cleaner, more readable code
  • Enterprise-ready architecture This is why Dependency Injection in Spring is a must-know concept when you learn Java seriously.

Code Examples (Java 21)
Example 1: Constructor Injection (Recommended Way)

// Dependency
@Component
public class PaymentService {

    public String processPayment() {
        return "Payment processed successfully";
    }
}

Enter fullscreen mode Exit fullscreen mode
// Dependent class
@Component
public class OrderService {

    private final PaymentService paymentService;

    // Constructor Injection
    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public String placeOrder() {
        return paymentService.processPayment();
    }
}

Enter fullscreen mode Exit fullscreen mode

✅ Why this is good

  • Dependencies are explicit
  • Easy to test
  • Immutable and safe Example 2: Setter Injection (Optional Dependencies)
@Component
public class NotificationService {

    public void notifyUser() {
        System.out.println("User notified");
    }
}

Enter fullscreen mode Exit fullscreen mode
@Component
public class UserService {

    private NotificationService notificationService;

    @Autowired
    public void setNotificationService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void registerUser() {
        notificationService.notifyUser();
    }
}

Enter fullscreen mode Exit fullscreen mode

✅ Useful when the dependency is optional or configurable.

Best Practices

  • Prefer constructor injection
    It makes dependencies clear and avoids null issues.

  • Avoid field injection
    It hides dependencies and makes testing difficult.

  • Program to interfaces, not implementations
    This improves flexibility and testability.

  • Keep beans focused
    One class should have one responsibility.

  • Let Spring manage object creation
    Avoid using new for Spring-managed beans.

Common Mistakes to Avoid

❌ Mixing manual object creation with Spring DI
❌ Overusing @Autowired unnecessarily
❌ Creating circular dependencies
❌ Ignoring interfaces in service design

Conclusion

Dependency Injection in Spring is not just a framework feature—it’s a design philosophy that makes Java applications clean, flexible, and maintainable.

By letting Spring handle object creation and dependency wiring, you write less boilerplate code and focus more on business logic. Whether you’re building a small REST API or a large enterprise system, mastering Dependency Injection will instantly improve the quality of your Java programming.

If you’re serious about learning Spring, DI is the first concept you should truly understand and practice.

Top comments (0)