Dependency Injection
Think of Spring Boot Dependency Injection as a marionette master that knows exactly which strings to pull to make your objects dance together.
Pre-Spring
// Without DI
public class CheckoutController {
    private PaymentService paymentService = new PaymentService(
        new FraudCheck(),
        new Database(),
        new EmailService()
        //more things that PaymentService may need...
    );
}
Every new is a commitment. Want to test it? You get the entire dependency tree. Need a mock database? Rewrite all constructors.
Spring's IoC Container
Imagine you're a chef in a kitchen. Instead of running to the farm for eggs, the dairy for milk, and the mill for flour, you shout "I need ingredients!" and they appear on your counter. **That's Spring's IoC (Inversion of Control) Container—**your personal assistant for Java objects.
How It Works
- Component scan: Spring scans your code for classes marked with annotations such as 
@Component,@Service,@Controller. - Beans creation: Spring instantiates these classes as "beans" (managed objects) and stores them in its container.
 - Dependency injection: When you need a bean, Spring automatically gets it for you from the container.
 
Ways to Do Dependency Injection
Field Injection
@RestController
public class CheckoutController {
    @Autowired
    private PaymentService paymentService;
    //Controller logic
}
Setter Injection
@RestController
public class CheckoutController {
    private PaymentService paymentService;
    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
    //Controller logic
}
Constructor Injection
@RestController
public class CheckoutController {
    private final PaymentService paymentService;
    public CheckoutController(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
    //Controller logic
}
Constructor injection is the recommended approach:
- No nulls – Your dependencies arrive fully assembled.
 - Immutable – Can’t accidentally swap your database for a toaster mid-request.
 - Testing-friendly – No Spring magic needed in unit tests.
 
Constructor Injection with Lombok
WIth Lombok, Constructor Injection is even simplified (and this is my recommended approach):
@RestController
@RequiredArgConstructor // <-- Lombok annotation
public class CheckoutController {
    private final PaymentService paymentService;
    //Controller logic
}
As a final note on this topic, I really recommend CodeAesthetic’s video “Dependency Injection, The Best Pattern”.