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:
@Service
public class CustomerService {
@Autowired
private CustomerRepository customerRepository;
}
2. Setter Injection
Spring will use the set method to inject the correct bean implementation.
Example:
@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;
}
}
3. Constructor Injection
You can inject the beans using the constructor. Spring will use the constructor arguments to inject the beans.
Example:
@Service
public class BillingService {
private final InvoiceGenerator invoiceGenerator;
@Autowired
public BillingService(InvoiceGenerator invoiceGenerator) {
this.invoiceGenerator = invoiceGenerator;
}
}
Since Spring Framework 4.3, the annotation in the constructor is no longer necessary. This will work in beans with a single constructor.
Example:
@Service
public class ReportService {
private ReportGenerator reportGenerator;
public ReportService(ReportGenerator reportGenerator) {
this.reportGenerator = reportGenerator;
}
}
If your bean defines multiple constructors and has the default empty constructor, Spring will pick the default to create the bean.
Example:
@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;
}
}
If you only have constructors with fields, you must annotate one with @Autowired
so Spring can locate and inject the beans.
@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;
}
}
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:
@Service
public class MandatoryService {
@Autowired
private OptionalBean mandatoryBean;
}
// Not defined as a bean
public class OptionalBean {
}
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:
@Service
public class MandatoryService {
@Autowired(required = false)
private OptionalBean mandatoryBean;
}
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!
Willian Moya (@WillianFMoya) / X (twitter.com)
Willian Ferreira Moya | LinkedIn