Introduction
Spring Boot is one of the most popular frameworks for building Java applications. One of its most powerful features is Dependency Injection (DI), which helps developers create flexible, maintainable, and scalable applications.
Dependency Injection allows Spring Boot to manage the creation and injection of objects automatically, reducing manual coding and improving application design.
What is Dependency Injection?
Dependency Injection is a design pattern where an object's dependencies are provided by an external source rather than being created inside the object itself.
A dependency is simply an object that another object needs to perform its work.
Without Dependency Injection
public class UserService {
private UserRepository userRepository = new UserRepository();
}
In this example, UserService creates its own UserRepository object. This creates tight coupling between the two classes.
With Dependency Injection
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
Here, Spring Boot automatically creates and injects the UserRepository object into UserService.
Why is Dependency Injection Important?
Dependency Injection provides several benefits:
- Reduces tight coupling between classes
- Improves code maintainability
- Makes unit testing easier
- Encourages reusable components
- Simplifies object management
These advantages make applications more scalable and easier to maintain over time.
Understanding Spring Beans
A Spring Bean is an object managed by the Spring IoC (Inversion of Control) Container.
Spring automatically creates beans for classes annotated with:
- @Component
- @Service
- @Repository
- @Controller
- @RestController
The Spring Container is responsible for creating, configuring, and managing these beans throughout the application's lifecycle.
Common Annotations Used in Dependency Injection
@Component
The @Component annotation tells Spring that a class should be managed as a bean.
@Component
public class EmailService {
public void sendEmail() {
System.out.println("Email Sent");
}
}
@Service
The @Service annotation is used for classes that contain business logic.
@Service
public class UserService {
public String getUserDetails() {
return "User Details";
}
}
@Repository
The @Repository annotation is used for database-related operations.
@Repository
public class UserRepository {
public String findUser() {
return "Arul";
}
}
@Autowired
The @Autowired annotation tells Spring to inject a required dependency automatically.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public String getUser() {
return userRepository.findUser();
}
}
Constructor Injection (Recommended)
Constructor Injection is considered the best practice in modern Spring Boot applications.
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUser() {
return userRepository.findUser();
}
}
Benefits of Constructor Injection
- Better testability
- Improved readability
- Supports immutability
- Clearly defines required dependencies
How Dependency Injection Works
The Spring Framework follows these steps:
- Spring Boot starts the application.
- Component scanning identifies annotated classes.
- Spring creates bean instances.
- Dependencies are detected.
- Required beans are injected automatically.
- The application becomes ready to handle requests.
This entire process is managed by the Spring IoC Container.
Real-World Example
Consider an Employee Management System.
Repository Layer
@Repository
public class EmployeeRepository {
public String getEmployee() {
return "Arul";
}
}
Service Layer
@Service
public class EmployeeService {
private final EmployeeRepository employeeRepository;
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public String fetchEmployee() {
return employeeRepository.getEmployee();
}
}
Controller Layer
@RestController
@RequestMapping("/employee")
public class EmployeeController {
private final EmployeeService employeeService;
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
@GetMapping
public String getEmployee() {
return employeeService.fetchEmployee();
}
}
Request Flow
Client Request → Controller → Service → Repository → Database
Spring automatically injects the required dependencies at each layer.
Top comments (0)