Constructor injection helps you give needed parts to a class when it is created. It makes your code clear and easy to test.
Constructor injection (preferred) in Spring Boot
public class MyService { private final Dependency dependency; public MyService(Dependency dependency) { this.dependency = dependency; } // class methods }
The dependency is passed in the constructor and saved in a final field.
Spring Boot automatically calls this constructor and gives the needed parts.
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(User user) {
userRepository.save(user);
}
}@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processOrder(Order order) {
paymentService.pay(order.getAmount());
}
}This program shows how Spring Boot uses constructor injection. The WelcomeController needs a GreetingService. Spring gives SimpleGreetingService to it when creating the controller. The program prints a welcome message.
import org.springframework.stereotype.Service; interface GreetingService { String greet(String name); } @Service class SimpleGreetingService implements GreetingService { public String greet(String name) { return "Hello, " + name + "!"; } } @Service class WelcomeController { private final GreetingService greetingService; public WelcomeController(GreetingService greetingService) { this.greetingService = greetingService; } public String welcome(String user) { return greetingService.greet(user); } } public class Application { public static void main(String[] args) { // Simulate Spring Boot creating beans and injecting dependencies GreetingService greetingService = new SimpleGreetingService(); WelcomeController controller = new WelcomeController(greetingService); System.out.println(controller.welcome("Alice")); } }
Constructor injection makes your classes easier to test because you can give fake parts in tests.
Always use final fields with constructor injection to keep dependencies safe and unchangeable.
Spring Boot prefers constructor injection because it clearly shows what a class needs.
Constructor injection gives dependencies when creating a class.
It helps keep code clear, safe, and easy to test.
Spring Boot recommends constructor injection as the best way to connect parts.
Practice
constructor injection in Spring Boot?Solution
Step 1: Understand constructor injection purpose
Constructor injection passes dependencies when creating the object, making them clear and fixed.Step 2: Benefits of explicit dependencies
This clarity helps testing because dependencies can be easily replaced with mocks.Final Answer:
It makes dependencies explicit and helps with testing. -> Option DQuick Check:
Constructor injection = explicit dependencies [OK]
- Thinking constructor injection creates objects automatically
- Confusing constructor injection with field injection
- Believing dependencies can be changed after creation
Solution
Step 1: Identify constructor injection pattern
Constructor injection requires a constructor that takes dependencies as parameters and assigns them.Step 2: Check each option
public class Service { private final Repo repo; public Service(Repo repo) { this.repo = repo; } } shows a constructor with a parameter and assigns it to a final field, which is correct.Final Answer:
public class Service { private final Repo repo; public Service(Repo repo) { this.repo = repo; } } -> Option AQuick Check:
Constructor with parameters = constructor injection [OK]
- Using @Autowired on fields instead of constructor
- Using setter methods instead of constructor
- Creating new dependency instances inside the class
printMessage method is called?\@Component
public class Printer {
private final MessageService service;
public Printer(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(service.getMessage());
}
}
\@Component
public class MessageService {
public String getMessage() {
return "Hello Spring!";
}
}Solution
Step 1: Understand constructor injection wiring
Spring injects MessageService into Printer via constructor, so service is not null.Step 2: Check method output
Calling service.getMessage() returns "Hello Spring!", which is printed.Final Answer:
Hello Spring! -> Option BQuick Check:
Injected service returns message [OK]
- Assuming service is null without injection
- Confusing field injection with constructor injection
- Expecting compilation error due to missing annotations
\@Component
public class UserService {
private final UserRepository repo;
public UserService() {
this.repo = null;
}
}Solution
Step 1: Check constructor parameters for injection
The constructor has no parameters, so Spring cannot inject UserRepository.Step 2: Understand consequence of no injection
repo is assigned null manually, so dependency is missing and will cause errors later.Final Answer:
Constructor does not accept UserRepository, so dependency is not injected. -> Option AQuick Check:
Constructor must have dependency parameters [OK]
- Forgetting to add parameters to constructor
- Thinking @Autowired is required on constructor in Spring Boot
- Instantiating dependencies manually inside constructor
PaymentService and NotificationService. How should you write the constructor to follow best practices for constructor injection?Solution
Step 1: Identify correct constructor injection with multiple dependencies
The constructor should accept all required dependencies as parameters and assign them.Step 2: Check options for best practice
public OrderService(PaymentService paymentService, NotificationService notificationService) { this.paymentService = paymentService; this.notificationService = notificationService; } correctly accepts both services and assigns them, following best practice.Final Answer:
public OrderService(PaymentService paymentService, NotificationService notificationService) { this.paymentService = paymentService; this.notificationService = notificationService; } -> Option CQuick Check:
Constructor with all dependencies = best practice [OK]
- Instantiating dependencies inside constructor
- Missing one of the dependencies in constructor
- Using @Autowired on constructor parameters unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
