In Spring, 5 Auto-wiring modes are supported.
- no – No auto-wiring.
- byName – Auto-wire a bean whose the name is same as the property.
- byType – Auto-wire a bean whose data type is compatible with the property.
- constructor – Auto-wire a bean whose date type is compatible with the property constructor argument.
- autodetect – If a default constructor with no argument is found, it will auto-wire by data type. Otherwise, it will auto-wire by constructor.
In case of any ambiguity in ‘byType’ or ‘constructor’ mode, an UnsatisfiedDependencyException will be thrown.
P.S The default mode is ‘no’.
A Customer and Person object for the demonstration.
package com.mkyong.common;
public class Customer
{
private Person person;
private int type;
private String action;
//getter and setter methods
@Override
public String toString() {
return "Customer [action=" + action + ", person=" + person +
",type=" + type + "]";
}
}
package com.mkyong.common;
public class Person
{
private String name;
private String address;
private int age;
//getter and setter methods
}
1. ‘no’ auto-Wiring mode
This is the default mode, you have to wire your bean explicitly by using the ‘ref’ attribute.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer">
<property name="person" ref="PersonBean" />
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
2. ‘byName’ auto-Wiring mode
It will auto-wire a bean whose name is same as the property.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="byName">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Run it
Customer [action=buy, person=null, type=1]
You will notice that the person property is not auto-wire, the person is still ‘null’, this is because the bean name ‘PersonBean’ is mismatch, it should be ‘person’. In ‘byName’ mode, the name of the auto-wire bean and the property name have to be exactly same (case sensitive as well).
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="byName">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="person" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Run it again
Customer [action=buy,
person=Person [address=address 123, age=28, name=mkyong], type=1]
Problem
In most cases, it is not practical to always make the name of the target bean the same as your property. In the end, you will always have a mixture of explicit wiring and auto-wiring environment.
3. ‘byType’ auto-Wiring mode
It will auto-wire a bean whose data type is same as the property.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="byType">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="person" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Run it
Customer [action=buy,
person=Person [address=address 123, age=28, name=mkyong], type=1]
Problem
Assume you have two person’s Beans as following :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="byType">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean1" class="com.mkyong.common.Person">
<property name="name" value="mkyong1" />
<property name="address" value="address 1" />
<property name="age" value="28" />
</bean>
<bean id="PersonBean2" class="com.mkyong.common.Person">
<property name="name" value="mkyong2" />
<property name="address" value="address 2" />
<property name="age" value="28" />
</bean>
</beans>
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.mkyong.common.Person] is defined:
expected single matching bean but found 2: [PersonBean1, PersonBean2]
The problem is sometimes there will be more than one beans are match with ‘byType’ criteria. In this case, Spring will throw an UnsatisfiedDependencyException exception.
4. ‘constructor’ auto-Wiring mode
It will auto-wire a bean whose date type is compatible with the property constructor argument. In this case, person bean will inject via Customer’s constructor automatically.
- Add a constructor to Customer class
package com.mkyong.common;
public class Customer
{
private Person person;
private int type;
private String action;
public Customer(Person person) {
this.person = person;
}
//getter and setter method
@Override
public String toString() {
return "Customer [action=" + action + ", person=" + person +
", type=" + type + "]";
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="constructor">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Run it
Customer [action=buy,
person=Person [address=address 123, age=28, name=mkyong], type=1]
Problem
The ‘constructor’ mode is facing the same problem with ‘byType’ auto-wire mode, if more than one beans are matched, Spring will throw an UnsatisfiedDependencyException exception as well. In addition, multiple constructors in a class may causing the ambiguity in constructor argument matching, in this case you will spend more time on resolving the issue.
5. ‘autodetect’ auto-Wiring mode
If a default constructor with no argument is found, it will auto-wire by data type. Otherwise, it will auto-wire by constructor.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer" autowire="autodetect">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Problem
It has the same problem with ‘byType’ and ‘constructor’, the worst is you may need to find out which mode is execute now.
Good Practice
It’s always good to combine the ‘auto-wire’ and ‘dependency-check’ feature together to make sure the property is auto-wire successfully.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer"
autowire="autodetect" dependency-check="objects">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address 123" />
<property name="age" value="28" />
</bean>
</beans>
Conclusion
In my opinion, this Spring ‘auto-wiring’ feature will reduce the readability of your bean configuration, and you even do not know which beans will wired from the bean configuration file, you are totally out of control of what will happened.
In practice, i recommend applying ‘auto-wiring’ only in small and simple component dependencies applications.