Spring Boot Dependency Injection

Dependency Injection (DI) is the technique Spring Boot uses to connect the different pieces of your app together automatically. Instead of creating objects manually, you ask Spring to provide them.

The Problem Without DI

Without DI — you create every object yourself:

public class OrderController {
    private OrderService service = new OrderService();     // Hardcoded
    //                             ↑ You create it manually
    //                             ↑ Hard to test, hard to swap
}

When your app grows, tracking and managing these object creations becomes a full-time job.

The Coffee Shop Analogy

You walk into a coffee shop and say "I need a latte." The barista (Spring) makes the latte and hands it to you. You do not grind beans, heat milk, or own an espresso machine. You just receive what you asked for. DI works the same way — Spring creates the objects your class needs and delivers them.

How DI Works in Spring Boot

  Spring Container (IoC Container)
  ┌────────────────────────────────────────┐
  │                                        │
  │  Creates:  OrderService                │
  │  Creates:  OrderRepository             │
  │  Creates:  OrderController             │
  │                                        │
  │  Wires together automatically          │
  │                                        │
  └────────────────────────────────────────┘
         │
         ▼ injects
  ┌───────────────┐       ┌──────────────┐
  │OrderController│  ────▶│ OrderService │
  └───────────────┘       └──────┬───────┘
                                 │
                                 ▼
                        ┌──────────────────┐
                        │ OrderRepository  │
                        └──────────────────┘

Constructor Injection (Recommended)

Pass dependencies through the constructor. This is the cleanest and most testable approach.

@RestController
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {   ← Spring injects here
        this.orderService = orderService;
    }

    @GetMapping("/orders")
    public List<Order> getOrders() {
        return orderService.findAll();
    }
}

Spring sees that OrderController needs an OrderService and automatically provides one.

@Autowired Annotation

When a class has only one constructor, Spring injects automatically. For field injection, use @Autowired — though constructor injection is preferred:

@Service
public class OrderService {

    @Autowired                              ← Spring injects this
    private OrderRepository repository;

    public List<Order> findAll() {
        return repository.findAll();
    }
}

Three Types of Injection Compared

Type                  How It Looks              Recommended?
─────────────         ─────────────────────     ────────────
Constructor           OrderService(Repo r)       YES ✓
Setter                setRepo(Repo r)            Sometimes
Field (@Autowired)    @Autowired Repo r          Avoid in production

Constructor injection is recommended because it makes dependencies explicit, allows immutable fields (final), and makes unit testing straightforward.

The IoC Container

IoC stands for Inversion of Control. In traditional programming, your code controls when objects get created. With IoC, you hand that control over to Spring.

Traditional:   Your code → creates → objects → uses them
IoC:           Spring → creates → objects → injects → your code uses them

The Spring IoC container is the engine behind DI. It holds all your beans, resolves their dependencies, and hands them out when needed.

What Happens at Startup

App starts
    │
    ▼
Spring scans all classes with @Component, @Service,
@Repository, @Controller, @RestController
    │
    ▼
Creates instances (beans) for each
    │
    ▼
Checks each bean's constructor — what does it need?
    │
    ▼
Injects matching beans
    │
    ▼
App is ready to handle requests

Summary

  • DI means Spring creates and provides objects your class needs
  • Constructor injection is the recommended approach
  • The IoC Container manages all bean creation and wiring
  • @Autowired tells Spring where to inject a dependency
  • DI makes code easier to test because you can swap real objects with mock ones

Leave a Comment

Your email address will not be published. Required fields are marked *