Constructor injection in spring:
In Spring, the dependency injection can be done in two ways – Setter Injection and Constructor Injection.
<property> tag is used to the value of a member variable. This property tag uses a setter method to initialize the value of a member variable. This is called setter injection.
If the class has a constructor that takes in the parameters for its member variables we use that constructor, instead of a setter, to initialize member variables. To implement this, we use constructor-arg tag.
Consider, we have a class Employee.java which has a member variable ‘Name’ of type String. (Note that the setName(String name ) is commented)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.j2eereference.spring; public class Employee { private String name; public Employee(String name) { this.name = name; } public String getName() { return name; } public void printInfo() { System.out.println("Name of the employee:"+getName()); } } |
spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="employee" class="com.j2eereference.spring.Employee" > <constructor-arg value="XYZ"/> </bean> </beans> |
Here, the value ‘XYZ’ is sent as a constructor argument when Employee object is initialized and it sets the value of ‘Name’ as XYZ. By using the ‘constructor-arg’, we tell Spring to inject the dependency using a constructor. Note that, unlike property tag, constructor-arg doesn’t have ‘name’ attribute.
Lets test it by calling’employee’ bean.
InfoApp.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.j2eereference.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class InfoApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Employee emp = (Employee)context.getBean("employee"); emp.printInfo(); } } |
Output : Name of the employee:XYZ
We can have as many constructors as we want.
Suppose there is another member variable ‘age’ of type int. We can have one more constructor which takes in a String and an int as parameters.
Employee.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.j2eereference.spring; public class Employee { private String Name; private int Age; public Employee(String name) { Name = name; } public Employee(String name, int age) { Name = name; Age = age; } public int getAge() { return Age; } public String getName() { return Name; } public void printInfo() { System.out.println("Name of the employee:"+getName()+"and age is:"+getAge()); } } |
And the spring.xml will look like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="employee" class="com.j2eereference.spring.Employee" > <constructor-arg value="XYZ"/> <constructor-arg value="20" /> </bean> </beans> |
Output : Name of the employee:XYZ and the age is:20
Here, though there are two constructors, Spring internally identifies the constructor that accepts two parameters and sets the values.Note that the values ‘XYZ’ and ’20’ are defined inside double quotes i.e., they are String type. But Spring takes care of converting the String value of age “20” to int value and then do the assignment.
But this could lead to a potential problem with constructor over-loading. Because the constructor to be called is decided at run-time depending on the constructor parameters. Suppose there is one more constructor which accepts a parameter of type int and sets the ‘Age’. And the bean configuration also has one constructor-arg. Since both int and String constructor parameters are represented in the same fashion and there is no way for Spring to know which constructor to call – whether to set Name or Age. To resolve this problem, we need to provide the information about the data type. We do this defining the ‘type’ property in the constructor-arg.
Here is how we set the type in the constructor-arg
1 2 3 4 |
<bean id="employee" class="com.j2eereference.spring.Employee" > <constructor-arg type="java.lang.String" value="XYZ"/> <constructor-arg type="int" value="20" /> </bean> |
Another way is by specifying the index. We can use index when have to resolve between multiple constructors depending on the order of the parameters. Here is how we specify the index
1 2 3 4 |
<bean id="employee" class="com.j2eereference.spring.Employee" > <constructor-arg index="0" value="XYZ"/> <constructor-arg index="1" value="20" /> </bean> |
What happens here is, it first looks for the constructor with two parameters. The first argument is set to value with index=0 and the second argument is set to a value with index=1
Leave a Reply