Learn the different ways @Autowired annotation can be used in Spring Boot with practical Java 21 examples, best practices, REST APIs, cURL requests, and more.
What are the Different Ways @Autowired Annotation Can Be Used in Spring Boot?
If you're learning Spring Boot, you've probably seen the @Autowired annotation everywhere. But what exactly does it do? More importantly, what are the different ways @Autowired annotation can be used?
Think of a restaurant.
A waiter takes your order, but you never have to worry about finding the chef, the kitchen, or the ingredients. Everything is automatically connected behind the scenes.
Spring Boot works in a similar way.
Instead of manually creating objects using new, Spring automatically creates and injects them wherever they're needed. This process is called Dependency Injection (DI), and @Autowired is one of the most popular ways to achieve it.
In this article, you'll learn:
- What
@Autowiredis - Different ways
@Autowiredannotation can be used - Which approach is recommended
- Complete Java 21 examples
- REST API example
- cURL request and response
- Best practices
- Common mistakes beginners make
Whether you're just starting Java programming or looking to learn Java with Spring Boot, this guide will help you understand @Autowired with confidence.
What is @Autowired?
@Autowired is a Spring Framework annotation that tells the Spring IoC (Inversion of Control) container:
"Find an object (bean) of the required type and inject it automatically."
Without dependency injection:
UserService service = new UserService();
With Spring:
@Autowired
private UserService service;
Spring creates the object and injects it automatically.
Why Use @Autowired?
Using @Autowired offers several benefits:
- Reduces boilerplate code
- Encourages loose coupling
- Improves maintainability
- Makes unit testing easier
- Lets Spring manage object lifecycles
Different Ways @Autowired Annotation Can Be Used
Spring supports multiple dependency injection techniques.
1. Constructor Injection (Recommended ✅)
Constructor injection is the recommended approach because:
- Dependencies become mandatory.
- Objects are immutable.
- Easier to write unit tests.
- Prevents partially initialized objects.
2. Field Injection
Spring injects the dependency directly into the field.
Although simple, it is not recommended for production code because:
- Harder to test
- Hidden dependencies
- Doesn't encourage immutability
3. Setter Injection
Setter injection is useful when a dependency is optional or needs to change after object creation.
4. Method Injection
Spring can inject dependencies into any method annotated with @Autowired.
Useful for initialization logic.
5. Optional Dependencies
Spring supports optional dependencies using:
@Autowired(required = false)Optional<T>ObjectProvider<T>
The latter two are generally preferred in modern Spring applications because they make optionality explicit.
Complete End-to-End Example (Constructor Injection)
Project Structure
src
└── main
├── java
│ └── com.example.demo
│ ├── DemoApplication.java
│ ├── controller
│ │ └── MessageController.java
│ └── service
│ └── MessageService.java
└── resources
└── application.properties
Code Example 1 – Constructor Injection (Recommended)
package com.example.demo.service;
import org.springframework.stereotype.Service;
/**
* Service managed by Spring.
*/
@Service
public class MessageService {
/**
* Returns a welcome message.
*/
public String getMessage() {
return "Hello from Spring Boot using Constructor Injection!";
}
}
package com.example.demo.controller;
import com.example.demo.service.MessageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* REST Controller demonstrating constructor injection.
*/
@RestController
public class MessageController {
private final MessageService messageService;
/**
* Spring automatically injects MessageService.
* Since there is only one constructor,
* @Autowired is optional in modern Spring.
*/
public MessageController(MessageService messageService) {
this.messageService = messageService;
}
@GetMapping("/message")
public String message() {
return messageService.getMessage();
}
}
Run the Application
./mvnw spring-boot:run
or
mvn spring-boot:run
Test the Endpoint
cURL
curl http://localhost:8080/message
Response
Hello from Spring Boot using Constructor Injection!
Code Example 2 – Setter Injection
package com.example.demo.service;
import org.springframework.stereotype.Service;
/**
* Service managed by Spring.
*/
@Service
public class GreetingService {
public String greeting() {
return "Setter Injection Example";
}
}
package com.example.demo.controller;
import com.example.demo.service.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Demonstrates setter injection.
*/
@RestController
public class GreetingController {
private GreetingService greetingService;
/**
* Spring injects GreetingService using this setter.
*/
@Autowired
public void setGreetingService(GreetingService greetingService) {
this.greetingService = greetingService;
}
@GetMapping("/greeting")
public String greeting() {
return greetingService.greeting();
}
}
Test the Endpoint
cURL
curl http://localhost:8080/greeting
Response
Setter Injection Example
Constructor vs Field vs Setter Injection
| Feature | Constructor | Field | Setter |
|---|---|---|---|
| Recommended | ✅ Yes | ❌ No | ✅ Sometimes |
| Immutable Dependencies | ✅ | ❌ | ❌ |
| Easy Unit Testing | ✅ | ❌ | ✅ |
| Mandatory Dependencies | ✅ | ❌ | ❌ |
| Optional Dependencies | ❌ | ❌ | ✅ |
Best Practices
- Prefer constructor injection because it makes dependencies explicit and easier to test.
- Avoid field injection in production applications since it hides dependencies and complicates unit testing.
- Keep services focused by following the Single Responsibility Principle (SRP).
-
Use
Optional<T>orObjectProvider<T>when a dependency is genuinely optional instead of relying on@Autowired(required = false). -
Annotate only Spring-managed components (such as
@Service,@Component,@Repository, or@Controller) so Spring can create and inject them correctly.
Common Mistakes
- Forgetting to annotate a class with
@Serviceor@Component. - Creating objects manually using
newinstead of letting Spring manage them. - Using field injection everywhere because it's shorter.
- Having multiple beans of the same type without resolving ambiguity using
@Qualifieror@Primary. - Attempting to autowire classes that are not managed by the Spring container.
Helpful Resources
- Oracle Java Documentation: https://docs.oracle.com/en/java/javase/21/
- Spring Framework Reference Documentation: https://docs.spring.io/spring-framework/reference/
- Spring Boot Reference Documentation: https://docs.spring.io/spring-boot/docs/current/reference/html/
Conclusion
Understanding what are the different ways @Autowired annotation can be used is an essential step in mastering Spring Boot. While Spring offers constructor, field, setter, method, and optional dependency injection, constructor injection is the recommended approach because it improves readability, immutability, maintainability, and testability.
As you continue to learn Java and build real-world Java programming applications, you'll discover that proper dependency injection makes your code cleaner, more modular, and easier to maintain.
Try the examples in this guide, experiment with the different injection styles, and observe how Spring automatically wires your application's components together.
Call to Action
Have questions about @Autowired, Spring Boot, or dependency injection? Leave a comment below and share your experience. If there's another Java or Spring topic you'd like to explore, feel free to ask—happy coding!
Top comments (1)
Nice breakdown.
One thing I think would make the article even more useful is a small
@Qualifierexample. Multiple beans of the same type are one of the first confusing situations beginners are hit with when learning about dependency injection.Spring needs to know which bean to choose.