Thursday 17 March 2011

Spring Constructor Dependency Injection tutorial (Xml approach)

In this example you will learn how to set a bean property via constructor injection. Here we use User:

class User{
private String name;
private int age;
private String country;
public User( String name, int age) {
this.name=name;
this.age=age;
}
public String toString() {
return name+" "+age;
}

}


The User bean class has two attributes viz. name and age. All the attributes are set through constructor injection. The toString() method of the User bean class is overridden to display the user object, in the main method.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="user" class="com.vaani.bean.User" >
<constructor-arg value="Kinshuk" />
<constructor-arg value="24"/>
</bean>
</beans>
Here the beans.xml file is used to do spring bean configuration. The following code shows how to set a property value thru constructor injection. We use <constructor-arg> to set the values.
Note – We have initialized the properties in the User bean in the order in which they occur in the constructor, i.e. first Name comes and then Age. But this is not it. We have many cases, which we have to deal. Lets deal with them one by one.

Case when Number of arguments in the constructor are equal and of the primary type

The constructor-arg element within the bean element is used to set the property value thru constructor injection. Since there is only one constructor in the User bean class, this code will work fine. When there is more than one constructor with the same number of arguments, then the following ambiguities will occur. Consider the following code:
class User{
private String name;
private int age;
private String country;
public User( int age, String country) {
this.age=age;
this.country=country;
}
public User(String name, String country) {
this.name=name;
this.country=country;
}
}

Now in bean descriptor file :

<bean id="user" class="com.vaani.bean.User" >
<constructor-arg value="24"/>
<constructor-arg value="India"/>
</bean>

Now which constructor do you think will be invoked? The first one with the int and the String argument, right? But for your surprise it will call the second constructor with both String arguments. Though we know the first argument is of type int and the second argument is of type String, spring interprets both as String arguments. To avoid this confusion you need to specify the type attribute of the constructor-arg element. Now with the following bean configuration, the first constructor will be invoked.

<bean id="user" class="com.vaani.bean.User" >
<constructor-arg type="int" value="24"/>
<constructor-arg type="java.lang.String" value="India"/>
</bean>


Case when constructor has same argument types , but in different order

Now consider this case. We have the following constructors in the User bean class.
public User(String name, int age)
{
this.name=name;
this.age=age;
}
public User( int age, String country)
{
this.age=age;
this.country=country;
}
The bean configuration file :
<bean id="user" class="com.vaani.bean.User" >
<constructor-arg type="int" value="24"/>
<constructor-arg type="java.lang.String" value="India"/>
</bean>

Now which constructor do you think will be called? The second constructor, right? But again for your surprise the first constructor will be called, this is because the order in which the arguments appear in the bean configuration file will not be considered while invoking the constructor. To solve this problem you can use the index attribute to specify the constructor argument index.

Here is the bean configuration file after adding the index attribute:

<bean id="user" class="com.vaani.bean.User" >
<constructor-arg index="0" type="int" value="24"/>
<constructor-arg index="1" type="java.lang.String" value="India"/>
</bean>
Now as expected, the second constructor will be invoked.

Summary


Constructor injection can be done through <constructor-arg>.Also, we came to now about attributes of <constructor-arg> – type and index.


Download the Source


Source can be downloaded from here.

No comments:

Post a Comment