What is the @Autowired annotation?
@Autowired is an annotation that is processed by
AutowiredAnnotationBeanPostProcessor, which can be put onto class constructor, field, setter method or config method. Using this annotation enables automatic Spring Dependency Resolution that is primarily based on types.
@Autowired has a property
required which can be used to tell Spring if dependency is required or optional. By default, the dependency is required. If
@Autowired with required dependency is used on top of constructor or method that contains multiple arguments, then all arguments are considered required dependency unless the argument is of type
Optional, is marked as
@Nullable, or is marked as
@Autowired(required = false).
@Autowired is used on top of Collection or Map then Spring will inject all beans matching the type into Collection and key-value pairs as BeanName-Bean into Map. Order of elements depends on the usage of
@Priority annotations and implementation of
@Autowired uses the following steps when resolving dependency:
- Match exactly by type, if only one found, finish
- If multiple beans of the same type found, check if any contains
@Primaryannotation, if yes, inject
@Primarybean and finish
- If no exactly one match exists, check if
@Qualifierexists for the field, if yes use
@Qualifierto find matching bean
- If still no exactly one bean found, narrow the search by using a bean name
- If still no exactly one bean found, throw an exception (
@Autowired with field injection
- Autowired fields can have any visibility level
- The injection is happening after Bean is created but before any init method (
@Bean(initMethod)) is called
- By default field is required, however, you can use
@Autowired(required = false)to indicate that field is not required.
After running this example, some of the beans are empty. This is because those are marked as Optional
RecordsService01 recordsHash = Optional.empty RecordsService01 recordsUtil = null RecordsService01 recordsValidator = null
@Autowired with constructor
The constructor can have any access modifier (public, protected, private, package-private).
If there is only one constructor in a class, there is no need to use
@Autowired on top of it, Spring will use this default constructor anyway and will inject dependencies into it.
If a class defines multiple constructors, then you are obligated to use
@Autowired to tell Spring which constructor should be used to create Spring Bean. If you will have a class with multiple constructors without any of constructor marked as
@Autowired then Spring will throw
By default all arguments in constructor are required, however, you can use
@Autowired(required = false) to indicate that parameter is not required.
In this example, there is only one constructor. And there is no need to use @Autowired. Spring already knows which dependencies need to be injected. All dependencies will be resolved.
In the next example, one of the constructors is annotated with @Autowired. And the bean will be created correctly.
Also, some of the dependencies marked as Optional and they will be empty or null. But constructor will be still called correctly.
@Autowired with the method injection
@Autowired method can have any visibility level and also can contain multiple parameters.
If the method contains multiple parameters, then by default it is assumed that in
@Autowired method all parameters are required. If Spring will be unable to resolve all dependencies for this method,
NoUniqueBeanDefinitionException will be thrown.
@Autowired(required = false) with the method, it will be invoked only if Spring can resolve all parameters.
If you want Spring to invoke method only with arguments partially resolved, you need to use
@Autowired method with parameter marked as
@Autowired(required = false) to indicate that this parameter is not required.
@Autowired with Collections
RecordsReader is an interface that is implemented by 4 classes. And we can inject all of these Beans into a List.
After running this example, we can see the next output:
RecordsService05 setRecordsReaders: SocketRecordsReader WebServiceRecordsReader FileRecordsReader DbRecordsReader
Because Spring injects all beans with a type of RecordReader to list. And the order is not random. It is dependent on the implementation of the components by annotations