You copy a Spring Boot project from YouTube. The app runs fine. Then you create your own service class, add it, and start the application, and Spring throws a wall of red errors.
Most freshers hit this point in their first Spring Boot project.
@Autowired looks simple because the annotation hides the hard part. Spring scans your application, creates objects, decides which object matches which dependency, and injects them automatically. When that process fails, debugging gets confusing fast.
This guide explains how it @Autowired actually works, where you should use it, where you should avoid it, and why most companies now prefer constructor injection in 2026.
What Does @Autowired Do in Spring Boot?
@Autowired tells Spring:
“Find an object of this type and inject it here.”
Example:
@Service
public class EmailService {
public void sendEmail() {
System.out.println("Email sent");
}
}@RestController
public class UserController {
@Autowired
private EmailService emailService;
@GetMapping("/send")
public String send() {
emailService.sendEmail();
return "Done";
}
}Spring creates the EmailService bean automatically because of this.
Then Spring sees @Autowired inside UserController and injects the object.
Without dependency injection, you would write:
EmailService emailService = new EmailService();Spring removes that manual object creation.
How Spring Finds the Right Bean to Inject
Spring scans classes marked with annotations like
@Component@Service@Repository@Controller
These classes become beans inside the Spring container.
When Spring sees:
@Autowired
private EmailService emailService;It searches for a bean whose type matches EmailService.
If exactly one bean exists, injection succeeds.
If zero beans exist, Spring throws an error.
If multiple beans exist, Spring gets confused unless you specify which bean you want.
By Type vs By Name Resolution
Spring primarily injects dependencies by type.
Example:
@Autowired
private PaymentService paymentService;Spring searches for a bean of its type PaymentService.
Bean names matter only when multiple beans of the same type exist.
Example:
@Service("upiService")
public class UpiPaymentService implements PaymentService {
}@Service("cardService")
public class CardPaymentService implements PaymentService {
}Now Spring sees two beans with the same interface type.
You must help Spring choose one.
3 Places You Can Use @Autowired

Spring allows dependency injection in 3 places:
- Field injection
- Constructor injection
- Setter injection
Each works differently.
1. Field Injection With @Autowired
This is the style most freshers learn first.
@Service
public class UserService {
@Autowired
private EmailService emailService;
public void registerUser() {
emailService.sendEmail();
}
}The dependency gets injected directly into the field.
This style looks clean because the code is short.
Why This Looks Clean But Has Problems
Field injection creates hidden dependencies.
When someone opens this class, they cannot immediately see what objects the class needs.
Testing also becomes harder.
Example:
UserService userService = new UserService();This object fails because it emailService was never injected.
You now need reflection or Spring test configuration to mock dependencies.
Another problem: field injection allows null dependencies more easily.
Many companies now reject field injection during code reviews unless there is a strong reason.
Interviewers also ask this question regularly in TCS Digital, Infosys Spring Boot rounds, and Cognizant backend interviews.
2. Constructor Injection (With or Without @Autowired)
Constructor injection is now the standard recommendation.
@Service
public class UserService {
private final EmailService emailService;
@Autowired
public UserService(EmailService emailService) {
this.emailService = emailService;
}
public void registerUser() {
emailService.sendEmail();
}
}The dependency becomes mandatory during object creation.
That makes the class safer.
Why Spring 4.3+ Makes @Autowired Optional Here
Since Spring Framework 4.3, you can skip @Autowired if the class has only one constructor.
Example:
@Service
public class UserService {
private final EmailService emailService;
public UserService(EmailService emailService) {
this.emailService = emailService;
}
}Spring automatically uses this constructor.
This is the style most modern Spring Boot projects follow in 2026.
Benefits:
- Easier unit testing
- Immutable dependencies with
final - Clear dependency visibility
- Better IDE support
- Safer object creation
Freshers often notice this style in company codebases and think something is missing because there is none.
Nothing is wrong. This is the preferred approach now.
3. Setter Injection With @Autowired
Setter injection injects dependencies through setter methods.
@Service
public class NotificationService {
private SmsService smsService;
@Autowired
public void setSmsService(SmsService smsService) {
this.smsService = smsService;
}
}This style is useful when the dependency is optional or may change later.
Example:
- optional integrations
- legacy systems
- configuration updates
Setter injection is less common in modern Spring Boot projects.
Most teams use constructor injection unless optional dependencies exist.
@Autowired With @Qualifier: Resolving Ambiguity

Problems start when multiple beans share the same type.
Example:
public interface PaymentService {
void pay();
}@Service
public class UpiPaymentService implements PaymentService {
}@Service
public class CardPaymentService implements PaymentService {
}Now this fails:
@Autowired
private PaymentService paymentService;Spring finds 2 matching beans.
You get an error similar to the following:
expected single matching bean but found 2When Two Beans of the Same Type Exist
This happens frequently in real projects.
Examples:
- multiple payment providers
- multiple database implementations
- different notification channels
- mock vs production services
Code Example: Using @Qualifier to Pick the Right Bean
@Service
public class CheckoutService {
@Autowired
@Qualifier("upiPaymentService")
private PaymentService paymentService;
}Spring now injects the correct bean.
You can also use constructor injection:
@Service
public class CheckoutService {
private final PaymentService paymentService;
public CheckoutService(
@Qualifier("upiPaymentService")
PaymentService paymentService) {
this.paymentService = paymentService;
}
}This is cleaner and easier to test.
@Autowired vs @Primary: Which Takes Priority?
@Primary gives one bean higher priority during injection.
Example:
@Service
@Primary
public class UpiPaymentService implements PaymentService {
}@Service
public class CardPaymentService implements PaymentService {
}Now this works:
@Autowired
private PaymentService paymentService;Spring injects UpiPaymentService automatically.
Difference Between @Qualifier and @Primary
| Feature | @Primary | @Qualifier |
|---|---|---|
| Purpose | Default bean selection | Explicit bean selection |
| Control level | Global | Local |
| Best for | Common default bean | Specific bean choice |
| Overrides | Can be overridden | Highest priority |
If both exist, it @Qualifier wins.
Example:
@Autowired
@Qualifier("cardPaymentService")
private PaymentService paymentService;Spring injects cardPaymentService even if another bean has @Primary.
The required = false. Option in @Autowired
By default, @Autowired dependencies are required.
If Spring cannot find the bean, the application fails during startup.
You can change this behavior:
@Autowired(required = false)
private DiscountService discountService;Now Spring skips injection if the bean does not exist.
When to Use Optional Injection
Useful cases:
- optional features
- plug-in systems
- environment-specific services
Example:
if(discountService != null) {
discountService.applyDiscount();
}Use this carefully.
Too many optional dependencies make debugging difficult.
Modern Spring projects often use Optional<T> instead because the intent becomes clearer.
Example:
private final Optional<DiscountService> discountService;Yes. But mostly with constructor injection.
Field injection still works technically. Spring has not removed it.
Most experienced developers avoid it because constructor injection creates safer classes.
The Constructor Injection Recommendation Explained
Constructor injection forces the class to declare its dependencies clearly.
Example:
public UserService(
EmailService emailService,
PaymentService paymentService
)Anyone reading the class instantly understands what it needs.
Field injection hides this information inside the class body.
Constructor injection also improves testing.
Example:
UserService userService =
new UserService(mockEmailService, mockPaymentService);No Spring context is required.
This matters during unit testing and interview machine coding rounds.
Code Comparison: @Autowired Field vs Constructor
| Field Injection | Constructor Injection |
|---|---|
| Shorter code | Better design |
| Harder to test | Easier to test |
| Hidden dependencies | Clear dependencies |
| Allows mutable fields | Supports final fields |
| Common in beginner tutorials | Common in production code |
If you are learning Spring Boot for placements, learn constructor injection early.
Many freshers know @Autowired.
Fewer understand why constructor injection matters.
That difference shows during interviews.
Common @Autowired Errors and Fixes
These errors appear constantly in beginner projects.
NoSuchBeanDefinitionException: Cause and Fix
Error:
No qualifying bean of type foundCommon causes:
1. Missing annotation
Wrong:
public class EmailService {
}Correct:
@Service
public class EmailService {
}2. Package scanning issue
Spring Boot scans packages below the main application class.
Example:
@SpringBootApplication
public class MyApplication {
}If itEmailService exists outside the package structure, Spring may not detect it.
3. Interface exists but implementation missing
Wrong:
@Autowired
private PaymentService paymentService;without any implementation bean.
Fix:
@Service
public class UpiPaymentService implements PaymentService {
}Expected At Least 1 Bean But Found 2: Fix
Error:
expected single matching bean but found 2Cause:
Multiple implementations exist.
Fix options:
Option 1: Use @Qualifier
Option 2: Use @Primary
Option 3: Inject all beans
Useful when you need all implementations together.
Frequently Asked Questions
1. Can @Autowired work without it @Component or @Service?
No. Spring can only inject classes that are registered as beans inside the Spring container. Annotations such as @Component, @Service, @Repository, and @Controller tell Spring to create and manage those objects. If the class is not registered as a bean, @Autowired injection fails with errors such as NoSuchBeanDefinitionException. This is part of Spring’s dependency injection mechanism.
Source: Spring Framework Documentation – Spring Framework Dependency Injection Docs
2. Is constructor injection better than field injection in Spring Boot?
Constructor injection is widely recommended in modern Spring applications because it makes dependencies explicit and easier to test. Spring Framework supports constructor-based dependency injection directly, and since Spring 4.3, @Autowired is optional when a class has only one constructor. Constructor injection also allows the use of final fields, which helps create immutable classes. Field injection still works, but many teams avoid it in production codebases because hidden dependencies make testing and maintenance harder.
Source: Spring Framework Documentation – Spring Framework Autowired Constructors Docs
3. What happens if multiple beans match the same @Autowired type?
Spring throws an error when more than one bean matches the required type and no specific bean is selected. The error usually states that Spring expected a single matching bean but found multiple candidates. Developers commonly fix this using @Qualifier to specify the bean name or @Primary to define a default bean. This behavior is part of Spring’s bean resolution process.
Source: Spring Framework Documentation – Spring Framework Qualifier Annotation Docs
4. Can @Autowired inject collections such as List or Map?
Yes. Spring can inject all beans of the same type into a collection such as List, Set, or Map. This feature is often used when applications need multiple implementations of the same interface, such as payment methods or notification services. Spring automatically discovers matching beans and adds them to the collection during dependency injection.
Source: Spring Framework Documentation – Spring Framework Collection Injection Docs
5. Does @Autowired work on static fields?
No. Spring does not support dependency injection directly on static fields because static members belong to the class itself, not to an object instance managed by the Spring container. Attempting to use @Autowired on a static field usually results in the field remaining null. Spring’s official documentation recommends using instance-based dependency injection instead.
Source: Spring Framework Documentation – Spring Framework Core Container Docs
Conclusion
@Autowired saves you from manual object creation, but understanding how Spring resolves dependencies matters more than memorizing the annotation itself.
Use constructor injection for most real-world Spring Boot projects in 2026. Learn @Primary, @Qualifier, and common error handling early because interviewers ask about these topics constantly.
Discover more from GroWithMoney
Subscribe to get the latest posts sent to your email.

