Setting bean dependencies in the configuration file is a good practice to follow in the Spring Framework; however, the Spring container can automatically autowire relationships between collaborating beans by inspecting the contents of BeanFactory
.
As we have seen, every member variable in the Spring bean has to be configured; for example, if a bean references another bean, we have to specify the reference explicitly. Autowiring is a feature provided by the Spring Framework that helps us reduce some of these configurations by intelligently guessing what the reference is.
The Spring Framework provides autowiring features where we don't need to provide bean injection details explicitly. The Spring container can autowire relationships between collaborating beans without using the <constructor-arg>
and <property>
elements. This immensely helps in cutting down the XML configuration. Spring is capable of automatically resolving dependencies at runtime. This automatic resolution of bean dependencies is also called autowiring
.
Spring wires a bean's properties automatically by setting the autowire
property on each <bean>
tag that you want to autowire. By default, autowiring is disabled. To enable it, specify the method of autowiring you want to apply using the autowire
attribute of the bean you want to autowire, as shown here:
<bean id="foo" class ="Foo" autowire="autowire-type" />
There are five modes of autowiring that Spring Container can use for autowiring. They are explained in the following table:
Let's demonstrate autowiring with examples.
In the EmployeeServiceImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.autowiring; public class EmployeeServiceImpl implements EmployeeService { private EmployeeDao employeeDao = null; public void setEmployeeDao(EmployeeDao employeeDao) { this.employeeDao = employeeDao; } }
In the EmployeeDaoImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.autowiring; public class EmployeeDaoImpl implements EmployeeDao { // ... }
In the preceding code snippet, the EmployeeServiceImpl
class has employeeDaofield
and a setter method.
This is a default mode, and you should use the explicit bean reference ref
for wiring.
In the beans.xml
file, you'll find the following code:
... <bean id="employeeService" class="org.packt.Spring.chapter2.autowiring.EmployeeServiceImpl"> <property name="employeeDao" ref="employeeDaoBean"></property> </bean> <bean id="employeeDaoBean" class="org.packt.Spring.chapter2.autowiring.EmployeeDaoImpl"> </bean> ...
Autowiring using the byName
option autowires a bean by its property name.
A Spring container looks at the properties of the beans on which the autowire
attribute is set using byName
in the configuration file. It then tries to match and wire its properties with the beans defined by the same names in the configuration file. If such a bean is found, it is injected into the property. If no such bean is found, an error is raised.
In the beans.xml
file, you'll find the following code:
... <bean id="employeeService" class="org.packt.Spring.chapter2.autowiring.EmployeeServiceImpl" autowire="byName"> </bean> <bean id="employeeDao" class="org.packt.Spring.chapter2.autowiring.EmployeeDaoImpl"> </bean> ...
In this case, since the name of the employeeDao
bean is the same as the employeeService
bean's property (EmployeeDao employeeDao
), Spring will autowire it via the setter method setEmployeeDao (EmployeeDao employeeDao)
.
In the beans.xml
file, you'll find the following code:
... <bean id="employeeService" class="org.packt.Spring.chapter2.autowiring.EmployeeServiceImpl" autowire="byName"> </bean> <bean id="employeeDaoBean" class="org.packt.Spring.chapter2.autowiring.EmployeeDaoImpl"> </bean> ...
In this case, since the name of the employeeDaoBean
bean is not the same as the employeeService
bean's property (EmployeeDao employeeDao
), Spring will not autowire it via the setter method, setEmployeeDao(EmployeeDao employeeDao)
. So, the employeeDao
property will get a null
value.
Autowiring using byType
enables Dependency Injection based on property data types.
The Spring container looks at each property's class type searching for a matching bean definition in the configuration file when autowiring a property in a bean. If no such bean is found, a fatal exception is thrown. If there is more than one bean definition found in the configuration, a fatal exception is thrown, and it will not allow byType
autowiring for that bean.
If there are no matching beans, nothing happens; the property is not set. So, to throw an error, use the dependency-check="objects"
attribute value.
In the beans.xml
file, you'll find the following code:
... <bean id="employeeService" class="org.packt.Spring.chapter2.autowiring.EmployeeServiceImpl" autowire="byType"> </bean> <bean id="employeeDaoBean" class="org.packt.Spring.chapter2.autowiring.EmployeeDaoImpl"> </bean> ...
In this case, since the data type of the employeeDaoBean
bean is the same as the data type of the employeeService
bean's property (EmployeeDao employeeDao
), Spring will autowire it via the setter method setEmployeeDao(EmployeeDao employeeDao)
.
Autowiring using the constructor applies to constructor arguments.
It will look for the class type of constructor arguments and perform autowiring using byType
on all constructor arguments. A fatal error is raised if there isn't exactly one bean of the constructor argument type in the container.
In the EmployeeServiceImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.autowiring; public class EmployeeServiceImpl implements EmployeeService { private EmployeeDao employeeDao; public EmployeeServiceImpl(EmployeeDao employeeDao) { this.employeeDao = employeeDao; } public EmployeeDao getEmployeeDao() { return employeeDao; } }
In the beans.xml
file, you'll find the following code:
... <bean id="employeeService" class="org.packt.Spring.chapter2.autowiring.EmployeeServiceImpl" autowire="constructor"> </bean> <bean id="employeeDaoBean" class="org.packt.Spring.chapter2.autowiring.EmployeeDaoImpl"> </bean> ...
In this case, since the data type of the employeeDaoBean
bean is the same as the constructor argument data type in the employeeService
bean's property (EmployeeDao employeeDao
), Spring autowires it via the constructor
: public EmployeeServiceImpl(EmployeeDao employeeDao)
.