Dependency Injection (Autowired)
Constructor injection is the way. Field injection is the trap.
The Amazon Delivery vs Self-Pickup Analogy:
If you need a new phone:
Without DI (Tight Coupling): You go to the factory yourself, build the phone, and bring it home. You are entirely dependent on the factory. If the factory closes, your work stops.
With DI (Loose Coupling): You order on Amazon saying "I need a phone." You don't care which warehouse Amazon gets it from. Amazon delivers it to your door. Here, Amazon is the Injector.
In Spring, the @Autowired annotation is the Amazon delivery boy. You write @Autowired in your class, and Spring automatically "injects" (delivers) the object into your variable.
- Field Injection:
@Autowireddirectly on the variable. Easy but not recommended — makes testing hard and fields cannot befinal. - Setter Injection:
@Autowiredon a setter method. Useful for optional dependencies. - Constructor Injection: Passing dependency via constructor. Highly Recommended by Spring team. Enables immutable
finalfields and easy testing with mocks.
In Spring Boot 3, if a class has only one constructor, @Autowired is optional!
package com.devinhyderabad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) throws Exception {
userService.saveUser("Ramesh");
}
}
@Repository
class DatabaseConnection {
public void save(String data) {
System.out.println("Saved " + data + " to H2 Database.");
}
}
@Service
class UserService {
private final DatabaseConnection dbConnection;
// Constructor Injection — @Autowired optional in Boot 3
public UserService(DatabaseConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void saveUser(String name) {
dbConnection.save(name);
}
}Field Injection — The Anti-Pattern
@Service
class BadUserService {
@Autowired
private DatabaseConnection dbConnection; // Not final, hard to test
public void saveUser(String name) {
dbConnection.save(name);
}
}Why avoid it? You can't make the field final. Unit testing requires Spring context or Reflection. Constructor injection solves all these problems.
Interview Question: "Why is Constructor Injection preferred over Field Injection?"
Answer: (1) Immutability: Constructor injection allows final dependencies, ensuring they cannot change after initialization. (2) Testability: You can pass mock objects to the constructor without Spring's test context. (3) Fail-fast: Missing dependencies fail at startup, not as NullPointerException at runtime.
Enterprise Note: All modern enterprise codebases strictly ban Field Injection using tools like SonarQube. Always use Constructor Injection.
Key Takeaways
- ✅ @Autowired tells Spring to inject a dependency into your class
- ✅ Constructor Injection is recommended over Field Injection
- ✅ Constructor Injection enables immutability (final fields) and testability
- ✅ Single-constructor classes don't need @Autowired in Spring Boot 3
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login