Introduction

When you start learning Spring Framework or Spring Boot, one concept you will encounter everywhere is Dependency Injection (DI).
Although the term might sound complicated, the concept is quite simple. Once you've understood DI, using Spring as a technology becomes a lot easier. This blog covers what Dependency Injection is, why it is important, how Spring implements it, and how you can use it in real projects with clear examples.
What Is a Dependency?
A dependency is any object that another object needs or requires.
Example:
class Car
In other words, what was happening was that students were being taught how to take tests rather than learning about the subject. Here, the car is dependent on the engine. Without an engine, the car cannot function. In this case, Engine is a dependency of Car.
Traditional Way: Creating Dependencies Manually
Before Spring, developers would normally create the dependencies within the class itself:
class Car
NOTE
Since the vortex-induced motion is more significant than the mean in-line motion, it corresponds to the circular frequency of the predominant eddies capable of inducing structural oscillations.
Problems with this approach:
Tight Coupling: The Car class is tightly coupled to the Engine class.
Hard to test, you cannot easily replace the engine with a mock or test version. Difficult to change if the constructor of the Engine changes, the Car class must also change. Poor maintainability: manual object creation results in scattered and inconsistent code.
Spring's Solution: Dependency Injection (DI)
Dependency Injection means
- Spring instantiates the objects and the dependencies for you.
- Spring injects them where needed.
- You don't have to manage how objects are created anymore.
This results in cleaner, flexible, reusable, and testable code.
Types of Dependency Injection in Spring

Spring supports three main types:
1. Constructor Injection (Recommended)
Spring passes the dependency through the class constructor.
2. Setter Injection
Spring calls the setter method to inject the dependency.
3. Field Injection (Not recommended)
Uses @Autowired directly on fields. This makes testing difficult.
Example for Constructor Injection in Spring Boot
Step 1: Create an Engine class
import org.springframework.stereotype.Component;
@Component
public class Engine
Step 2: Injecting the Engine into the Car
import org.springframework.stereotype.Component;
@Component
public class Car
Step 3: Run the application
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
Output:
The engine started!
The car is moving…
Notice that you never created objects like Engine or Car manually. Spring handled everything.
How Does Spring Handle This Internally?
Spring uses an IoC (Inversion of Control) Container.
This container:
- Scans for classes annotated with @Component, @Service, @Controller, or @Repository within the application.
- Creates objects called Beans for them.
- Stores these beans inside the container.
- injects them into other classes whenever needed.
This is the very process that enables Dependency Injection.
Why Dependency Injection Matters
- Loose Coupling: Classes don't need to create their own dependencies.
- Easier Testing: You can easily replace dependencies with mock objects.
- Reusability: The same object can be reused across multiple classes.
- Cleaner Code: It eliminates the need to continually create new objects.
- Maintainability: Changes in one class don't ripple to other classes unnecessarily.
Real-World Example: Service – Repository Injection
Repository Layer
@Repository
public class StudentRepository
Service Layer
@Service
public class StudentService
Controller Layer
@RestController
public class StudentController
This is one of the most common and practical uses of Dependency Injection in Spring Boot.
Conclusion
One of the central features of the Spring Framework is Dependency Injection. It helps Spring handle object creation, simplify code, enhance testability, and decrease coupling. In other words, you focus on writing logic, while Spring takes care of the creation and life cycle of objects your application will need.


