Autowiring :
- XML –> No (Default), byType, byName, constructor.
[byType, and byName uses setter injection]
- Annotations -> @Autowired, @Qualifier
Auto-wiring works on reference types.
autowire is an attribute of <bean> tag. This attribute defines how the autowiring should be done. The values of autowire attribute are byName, byType, constructor, no and default.
For @Autowired annotation to work, we also need to enable annotation based configuration in spring bean configuration file. This can be done by context:annotation-config element.
<context:annotation-config />
- byName : Spring container looks for bean name same as property name of the class for autowiring.
- byType : Spring container selects the bean by class type for autowiring.
- constructor : Spring container uses constructor based autowiring.
- no : No Autowiring. Use
refattribute to resolve dependency. - default : The default autowiring is “no”. Default autowiring will inherit parent bean autowiring if nested.
Spring Bean Autowire “byName”
In case of byName auto-wire, spring container looks for bean in XML configuration whose name is same as class property name.
If there is more than one bean of same class with different bean name in our XML configuration, the autowiring will not conflict and take the matching bean name with class property name.
Ex:
<bean name="employee" class="com.rdayala.bean.Employee" autowire="byName"> <property name="empName" value="Manohar Parikar"/> </bean>
Spring Bean Autowire “byType”
In case of byType autowiring, spring container looks for the class type. If in our XML configuration, there is more than one eligible candidate by class type for autowiring, the container will through error. There are three scenarios that may happen in case of by type autowiring.
- If in the container, there is only one bean of required class type then auto-wiring is performed.
- If there is more than one bean of same class type in the container, a fatal error is thrown and auto-wiring is not performed. [NoUniqueBeanDefinitionException]
- If there is no bean of required class type in the container, obviously no auto-wiring is performed and also no error is thrown. The object will have null value.
Ex:
<bean name="employee" class="com.rdayala.bean.Employee" autowire="byType"> <property name="empName" value="Narendra Modi"/> </bean>
Spring Bean Autowire “constructor”
constructor auto-wiring is the analogous to byType auto-wiring. This is almost similar to autowire byType, the only difference is that constructor is used to inject the dependency. POJO class should have a parameterized constructor.
Ex:
<bean name="employee" class="com.rdayala.bean.Employee" autowire="constructor"> <constructor-arg name="empName" value="Manohar Parikar"/> </bean>
Spring Bean Autowire “no” and “default”
Use ref attribute to resolve dependency. “default” autowiring is “no”. But when the bean is nested bean, then the default autowiring is parent bean autowiring.
Ex:
<bean id="employee" class="com.concretepage.bean.Employee"> <constructor-arg name="address" ref="address"/> <constructor-arg name="empName" value="Manohar Parikar"/> </bean>
@Autowired annotation :
We can use Spring @Autowired annotation for spring bean autowiring.
@Autowired annotation can be applied on fields and methods for autowiring byType.
We can also use @Autowired annotation on constructor for constructor based spring autowiring.
When using @Autowired annotation, the default autowiring in spring is by type.
Note
The @Autowired annotation is auto wire the bean by matching data type. Default auto-wiring in Spring is byType.
Auto-wiring by Type
In the below example, only one bean matches for the dependency. So, autowiring automatically injects the dependency using the type.
@Component
public class BubbleSortAlgorithm implements SortingAlgorithm {
.....
}
public class QuickSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class BinarySearchImpl {
// autowiring by type - injects BubbleSortAlgorithm here
@Autowired
SortingAlgorithm sortAlgorithm;
....
}
*** Suppose, if there are multiple candidate classes available for dependency injection, how does Spring Framework chose one class for injection?
Solution 1 : Using @Primary annotation
In such a case, make one of the component class as @Primary. By making one class as @Primary, we are giving it a priority for injection.
@Component
@Primary
public class BubbleSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class QuickSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class BinarySearchImpl {
@Autowired
SortingAlgorithm sortAlgorithm; // uses BubbleSortAlgorithm
....
}
Solution 2 : Auto-wiring by Name
The name of the instance variable is used to solve the dependency injection conflict.
The field name should be something same as Bean name.
@Component
public class BubbleSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class QuickSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class BinarySearchImpl {
// autowiring by name. name of the field same as bean name.
@Autowired
SortingAlgorithm quickSortAlgorithm; // uses QuickSortAlgorithm
....
}
Note : @Primary has higher priority over auto-wiring by name.
Solution 3 : Using @Qualifier annotation
syntax : @Qualifer(“<bean_name>”) –> bean name as given in XML configuration file or defined while declaring @Component.
@Component
@Qualifier("bubble")
public class BubbleSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
@Qualifier("quick")
public class QuickSortAlgorithm implements SortingAlgorithm {
.....
}
@Component
public class BinarySearchImpl {
@Autowired
@Qualifier("quick")
SortingAlgorithm sortAlgorithm; // uses QuickSortAlgorithm
....
}
Dependency checking
By default, the @Autowired will perform the dependency checking to make sure the property has been wired properly.
When Spring can’t find a matching bean to wire, it will throw an exception. To fix it, you can disable this checking feature by setting the “required” attribute of @Autowired to false.
package com.mkyong.common;
import org.springframework.beans.factory.annotation.Autowired;
public class Customer
{
@Autowired(required=false)
private Person person;
private int type;
private String action;
//getter and setter methods
}
In the above example, if the Spring can’t find a matching bean, it will leave the person property unset.
More reading :
https://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/