DEV Community

realNameHidden
realNameHidden

Posted on

What is the Purpose of the @Autowired Annotation in Spring Boot?

Learn what the @Autowired annotation in Spring Boot is, how dependency injection works, practical examples, best practices, and common mistakes to avoid.

What is the Purpose of the @Autowired Annotation in Spring Boot?

Spring Boot simplifies Java application development by handling much of the configuration and object management for you. One of the most commonly used annotations in Spring Boot is @Autowired.

If you're new to Spring Boot, you've probably seen @Autowired in tutorials and projects and wondered:

"Why do we need this annotation, and what problem does it solve?"

In this guide, you'll learn the purpose of the @Autowired annotation in Spring Boot, how it works behind the scenes, when to use it, and the best practices every Java developer should follow.

Introduction

Imagine you're building a large house.

The house needs electricians, plumbers, carpenters, and painters. Instead of hiring and managing each worker yourself, you hire a project manager who automatically brings in the right people whenever they're needed.

Spring Boot works similarly.

Rather than manually creating every object using the new keyword, Spring's Inversion of Control (IoC) Container acts as the project manager. It creates, manages, and injects required objects automatically.

This is where the @Autowired annotation in Spring Boot becomes useful.

The @Autowired annotation tells Spring:

"Please find the required dependency and inject it here automatically."

This mechanism is known as Dependency Injection (DI), one of the most important concepts in Java programming and enterprise application development.

Core Concepts

What is @Autowired?

The @Autowired annotation is used by Spring to automatically inject dependencies into a class.

Instead of:

UserService userService = new UserService();
Enter fullscreen mode Exit fullscreen mode

Spring creates and manages the object for you.

Example:

@Autowired
private UserService userService;
Enter fullscreen mode Exit fullscreen mode

Spring looks for a matching bean in its container and injects it automatically.

What is a Dependency?

A dependency is simply an object that another object needs to perform its work.

For example:

  • UserController depends on UserService
  • UserService depends on UserRepository

Visual representation:

UserController
      ↓
 UserService
      ↓
UserRepository
Enter fullscreen mode Exit fullscreen mode

Without dependency injection, you would manually create each object.

With Spring Boot, the framework handles it automatically.

How Does @Autowired Work?

When the Spring application starts:

  1. Spring scans the application.
  2. It finds classes marked with annotations such as:
  • @Component
  • @Service
  • @Repository
  • @Controller
  • @RestController
    1. Spring creates objects (beans).
    2. Whenever it finds @Autowired, it searches for a matching bean.
    3. The dependency is injected automatically.

Benefits of @Autowired

1. Reduced Boilerplate Code

You don't need to manually create objects.

2. Loose Coupling

Classes depend on interfaces rather than implementations.

3. Easier Testing

Dependencies can be mocked easily during unit testing.

4. Better Maintainability

Spring manages object lifecycle and dependencies.

5. Cleaner Code

Business logic remains focused on business requirements.

Common Use Cases

The @Autowired annotation in Spring Boot is commonly used for:

Service Injection

@Autowired
private UserService userService;
Enter fullscreen mode Exit fullscreen mode

Repository Injection

@Autowired
private UserRepository userRepository;
Enter fullscreen mode Exit fullscreen mode

Configuration Bean Injection

@Autowired
private ObjectMapper objectMapper;
Enter fullscreen mode Exit fullscreen mode

Third-Party Bean Injection

@Autowired
private RestTemplate restTemplate;
Enter fullscreen mode Exit fullscreen mode

Code Example 1: Constructor-Based Dependency Injection (Recommended)

This is the preferred approach in modern Spring Boot applications.

Project Structure

src
 └── main
     └── java
         └── com.example.demo
              ├── controller
              │     └── MessageController.java
              ├── service
              │     └── MessageService.java
              └── DemoApplication.java
Enter fullscreen mode Exit fullscreen mode

MessageService.java

package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class MessageService {

    public String getMessage() {
        return "Hello from MessageService!";
    }
}
Enter fullscreen mode Exit fullscreen mode

MessageController.java

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;

@RestController
public class MessageController {

    private final MessageService messageService;

    // Spring automatically injects MessageService
    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    @GetMapping("/message")
    public String getMessage() {
        return messageService.getMessage();
    }
}
Enter fullscreen mode Exit fullscreen mode

DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Run the Application

mvn spring-boot:run
Enter fullscreen mode Exit fullscreen mode

Request

curl http://localhost:8080/message
Enter fullscreen mode Exit fullscreen mode

Response

Hello from MessageService!
Enter fullscreen mode Exit fullscreen mode

Why This Example is Better

Constructor injection:

  • Makes dependencies explicit
  • Supports immutability
  • Easier unit testing
  • Recommended by Spring team

Code Example 2: Injecting a Repository into a Service

This example demonstrates a realistic Spring Boot REST API.

UserRepository.java

package com.example.demo.repository;

import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {

    public String findUserName() {
        return "Sample User";
    }
}
Enter fullscreen mode Exit fullscreen mode

UserService.java

package com.example.demo.service;

import com.example.demo.repository.UserRepository;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    private final UserRepository userRepository;

    // Constructor injection
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getUserName() {
        return userRepository.findUserName();
    }
}
Enter fullscreen mode Exit fullscreen mode

UserController.java

package com.example.demo.controller;

import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class UserController {

    private final UserService userService;

    // Dependency injected automatically
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/users/name")
    public Map<String, String> getUserName() {

        return Map.of(
                "username",
                userService.getUserName()
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Request

curl http://localhost:8080/users/name
Enter fullscreen mode Exit fullscreen mode

Response

{
  "username": "Sample User"
}
Enter fullscreen mode Exit fullscreen mode

Field Injection vs Constructor Injection

Field Injection

@Autowired
private UserService userService;
Enter fullscreen mode Exit fullscreen mode

Constructor Injection

private final UserService userService;

public UserController(UserService userService) {
    this.userService = userService;
}
Enter fullscreen mode Exit fullscreen mode

Modern Spring Boot applications prefer constructor injection because it improves testability, readability, and maintainability.

Since Spring Framework 4.3, if a class has only one constructor, @Autowired is optional.

Example:

public UserController(UserService userService) {
    this.userService = userService;
}
Enter fullscreen mode Exit fullscreen mode

Spring automatically performs injection.

Best Practices

1. Prefer Constructor Injection

✅ Recommended

public UserController(UserService userService) {
    this.userService = userService;
}
Enter fullscreen mode Exit fullscreen mode

❌ Avoid excessive field injection

@Autowired
private UserService userService;
Enter fullscreen mode Exit fullscreen mode

2. Use Interfaces for Loose Coupling

Good:

private final UserService userService;
Enter fullscreen mode Exit fullscreen mode

Instead of tightly coupling to implementation classes.

3. Keep Beans Small and Focused

Each service should have a single responsibility.

Avoid creating large "God Classes."

4. Avoid Manual Object Creation

Incorrect:

UserService service = new UserService();
Enter fullscreen mode Exit fullscreen mode

Correct:

@Autowired
private UserService userService;
Enter fullscreen mode Exit fullscreen mode

Or constructor injection.

5. Let Spring Manage Your Components

Ensure classes are annotated properly:

@Service
@Repository
@Component
@RestController
Enter fullscreen mode Exit fullscreen mode

Otherwise Spring cannot discover and inject them.

Common Errors and Solutions

Error: No qualifying bean found

Example:

No qualifying bean of type found
Enter fullscreen mode Exit fullscreen mode

Cause

Spring cannot find a bean to inject.

Fix

Ensure the class is annotated:

@Service
public class UserService {
}
Enter fullscreen mode Exit fullscreen mode

Error: Multiple Beans Found

Example:

expected single matching bean but found 2
Enter fullscreen mode Exit fullscreen mode

Fix

Use:

@Qualifier("beanName")
Enter fullscreen mode Exit fullscreen mode

Example:

@Autowired
@Qualifier("emailService")
private NotificationService service;
Enter fullscreen mode Exit fullscreen mode

FAQ

Is @Autowired mandatory in Spring Boot?

No. When using a single constructor, Spring automatically injects dependencies without @Autowired.

What is dependency injection in Java?

Dependency Injection is a design pattern where required objects are provided by a framework rather than being created manually.

What is the difference between @Component and @Autowired?

  • @Component creates a Spring bean.
  • @Autowired injects a Spring bean.

Can @Autowired inject interfaces?

Yes.

Spring injects the implementation class that matches the interface type.

Helpful Resources

Conclusion

The @Autowired annotation in Spring Boot plays a vital role in implementing Dependency Injection. It allows Spring to automatically provide the objects your application needs, reducing boilerplate code and improving maintainability.

Key takeaways:

  • @Autowired injects dependencies automatically.
  • It works with Spring-managed beans.
  • Constructor injection is the recommended approach.
  • It improves testability and loose coupling.
  • Modern Spring Boot applications often don't require @Autowired on a single constructor.

If you're learning Java programming or trying to learn Java enterprise development, mastering dependency injection and the @Autowired annotation in Spring Boot is an essential step toward building scalable applications.

Call to Action

Have you used the @Autowired annotation in Spring Boot in your projects? Share your experience, questions, or challenges in the comments below. If you'd like to learn Java and Spring Boot faster, feel free to ask your questions, and let's discuss them together!

Top comments (0)