Vishal's Blog
Header

14 - Spring Autowiring: Modes & Best Practices

Autowiring is the mechanism Spring uses to automatically resolve and inject dependencies between beans.
When used correctly, autowiring reduces boilerplate code and improves readability. When misused, it can cause ambiguity and runtime errors.

This post explains how autowiring works, the available modes, and best practices you should follow in real-world Spring Boot applications.


1. What Is Autowiring?

Autowiring allows Spring to automatically inject required dependencies into a bean without explicit configuration.

Instead of manually creating and wiring objects, Spring identifies the required dependencies and injects them at runtime using the IoC container.


2. Autowiring Modes in Spring

Spring supports multiple autowiring modes. Some are legacy (XML-based), while others are modern and annotation-based.


2.1 Constructor Injection (Recommended)

Dependencies are injected through the constructor.

@Service
public class OrderService {

    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

Why constructor injection is best:

  • Makes dependencies explicit
  • Ensures immutability
  • Simplifies unit testing
  • Prevents NullPointerException
  • Preferred by Spring team

In Spring Boot 2+, @Autowired is optional for constructors with a single parameter.


2.2 Setter Injection

Dependencies are injected through setter methods.

@Service
public class NotificationService {

    private EmailService emailService;

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}

When to use:

  • Optional dependencies
  • Dependencies that may change

2.3 Field Injection (Not Recommended)

Dependencies are injected directly into fields.

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
}

Why avoid field injection?

  • Hard to test
  • Hides dependencies
  • Breaks immutability
  • Difficult to mock

Use it only in quick demos or legacy code.


3. Resolving Multiple Bean Candidates

If Spring finds more than one matching bean, it throws:

NoUniqueBeanDefinitionException

To resolve this, use:


3.1 @Qualifier

@Autowired
@Qualifier("paypalPaymentService")
private PaymentService paymentService;

3.2 @Primary

@Service
@Primary
public class DefaultPaymentService implements PaymentService { }

Spring will inject the primary bean by default.


4. Autowiring by Type vs Name

Spring resolves dependencies in this order:

  1. By Type
  2. By Qualifier
  3. By Bean Name

Understanding this order helps avoid injection conflicts.


5. Autowiring in Spring Boot

Spring Boot enhances autowiring by:

  • Auto-configuring common dependencies
  • Providing sensible defaults
  • Reducing explicit configuration

Example:

@RestController
public class HelloController {

    private final HelloService helloService;

    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }
}

Spring Boot automatically injects HelloService without extra configuration.


6. Common Autowiring Pitfalls

❌ Multiple beans without qualifier

Always specify @Qualifier or @Primary.

❌ Using field injection everywhere

Prefer constructor injection.

❌ Circular dependencies

Refactor design or use setter injection if unavoidable.

❌ Injecting concrete classes instead of interfaces

Depend on abstractions, not implementations.


7. Best Practices

✔ Prefer constructor injection

✔ Use interfaces for dependencies

✔ Avoid field injection

✔ Use @Qualifier for multiple implementations

✔ Keep beans stateless when possible

These practices make applications cleaner, testable, and scalable.


8. Summary

  • Autowiring automatically injects dependencies.
  • Constructor injection is the recommended approach.
  • Setter injection is useful for optional dependencies.
  • Field injection should be avoided.
  • Use @Qualifier and @Primary to resolve conflicts.

Proper autowiring is critical for clean Spring architecture.


What's Next?

Next post:

15 - DispatcherServlet & Request Flow in Spring MVC

We’ll explore how requests travel through Spring from controller to response.