DEV Community

Willian Ferreira Moya
Willian Ferreira Moya

Posted on • Originally published at springmasteryhub.com

Understanding @Autowired in Spring: A Comprehensive Guide

Introduction

The @Autowired annotation is one of the most common annotations when working with Spring. Its objective is simple: to tell Spring to inject a dependency bean into our beans. In other words, it will pick an instance of a bean from the Spring IoC (Inversion of Control) container and set it into our components. This will be done at the start of the Spring application when it initializes and configures all the beans.

Let’s see examples of how to work with this annotation:

1. Field Injection

The annotation is placed on the field. Spring will automatically locate and inject the correct bean implementation into it.

Example:

javaCopy code
@Service
public class CustomerService {

    @Autowired
    private CustomerRepository customerRepository;

}

Enter fullscreen mode Exit fullscreen mode

2. Setter Injection

Spring will use the set method to inject the correct bean implementation.

Example:

javaCopy code
@Service
public class OrderService {

    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
    private ProductCatalog productCatalog;

    @Autowired
    public void setProductCatalog(ProductCatalog productCatalog) {
        log.info("Injecting by set");
        this.productCatalog = productCatalog;
    }
}

Enter fullscreen mode Exit fullscreen mode

3. Constructor Injection

You can inject the beans using the constructor. Spring will use the constructor arguments to inject the beans.

Example:

javaCopy code
@Service
public class BillingService {

    private final InvoiceGenerator invoiceGenerator;

    @Autowired
    public BillingService(InvoiceGenerator invoiceGenerator) {
        this.invoiceGenerator = invoiceGenerator;
    }
}

Enter fullscreen mode Exit fullscreen mode

Since Spring Framework 4.3, the annotation in the constructor is no longer necessary. This will work in beans with a single constructor.

Example:

javaCopy code
@Service
public class ReportService {

    private ReportGenerator reportGenerator;

    public ReportService(ReportGenerator reportGenerator) {
        this.reportGenerator = reportGenerator;
    }
}

Enter fullscreen mode Exit fullscreen mode

If your bean defines multiple constructors and has the default empty constructor, Spring will pick the default to create the bean.

Example:

javaCopy code
@Service
public class NotificationService {

    private static final Logger log = LoggerFactory.getLogger(NotificationService.class);
    private EmailSender emailSender;
    private SmsSender smsSender;

    public NotificationService() {
            log.info("Spring will pick this one");
    }

    public NotificationService(EmailSender emailSender) {
        log.info("Injecting email sender");
        this.emailSender = emailSender;
    }

    public NotificationService(EmailSender emailSender, SmsSender smsSender) {
        log.info("Injecting both");
        this.emailSender = emailSender;
        this.smsSender = smsSender;
    }
}

Enter fullscreen mode Exit fullscreen mode

If you only have constructors with fields, you must annotate one with @Autowired so Spring can locate and inject the beans.

javaCopy code
@Service
public class NotificationService {

    private static final Logger log = LoggerFactory.getLogger(NotificationService.class);
    private EmailSender emailSender;
    private SmsSender smsSender;

    public NotificationService(EmailSender emailSender) {
        this.emailSender = emailSender;
    }

    @Autowired
    public NotificationService(EmailSender emailSender, SmsSender smsSender) {
        log.info("Spring will inject this one");
        this.emailSender = emailSender;
        this.smsSender = smsSender;
    }
}

Enter fullscreen mode Exit fullscreen mode

Otherwise, Spring will throw a BeanInstantiationException.

4. Marking as Not Required

By default, the fields annotated with @Autowired are required. If Spring does not find any instance of the correct bean to inject, it will fail to launch.

Example:

javaCopy code
@Service
public class MandatoryService {

    @Autowired
    private OptionalBean mandatoryBean;

}

// Not defined as a bean
public class OptionalBean {
}

Enter fullscreen mode Exit fullscreen mode

Spring will tell you at the start of the application:

Field mandatoryBean in com.spring.mastery.autowired.MandatoryService required a bean of type 'com.spring.mastery.autowired.OptionalBean' that could not be found.

But it will start if you set the property as required false.

Example:

javaCopy code
@Service
public class MandatoryService {

    @Autowired(required = false)
    private OptionalBean mandatoryBean;

}

Enter fullscreen mode Exit fullscreen mode

Conclusion

Now you understand all your options when using @Autowired in your project!

If you like this topic, make sure to follow me. In the following days, I’ll be explaining more about Spring annotations! Stay tuned!

Follow me!

References

Top comments (0)