In this Spring uses one of the constructors of a bean to provide its dependencies. This is done by using <constructor-arg> tag in the xml configuration file. This is also known as constructor-based dependency injection.
Injecting simple values
Suppose we have a Student class as:
Student.java
Here student class has a constructor with two arguments.
To provide the values for these arguments following code will be used in xml file.
ApplicationContext.xml
Note that one argument age is of type int but in xml file we are passing it as String. Spring will convert this automatically to int type. Spring can convert a value supplied in string format to basic types such as int, long, String, boolean, etc.
To run this example write another class:
Test.java
Output:
Injecting reference to other beans
Instead of providing simple values of basic types like int, String, boolean etc. we can also provide references to other beans as values in <constructor-arg> tag.
Suppose Student class has a another constructor in addition to the previous one:
Then for this we have to use following code in xml file:
Note that here we have used ref attribute instead of value attribute in <constructor-arg> tag of bean with id student1.
No-arg constructor
Suppose we do not provide any <constructor-arg> tag in the bean definition of Student as:
It will give an error:
Caused by: java.lang.NoSuchMethodException: di.constructor.Student.<init>()
This is because it will then try to invoke a no-argument constructor in Student class but we have not provided any such constructor yet. So add following constructor to Student class:
Now if you run the program it will print:
Using 'name', 'type' and 'index' attributes.
Note the order of arguments of Student's constructor.
Now suppose in xml file if we provide their values in opposite order :
This will give error. To resolve this we can use name attribute of <constructor-arg> tag as:
Or we can also use index attribute as:
Note that first argument of constructor is considered as at index 0.
Or we can aslo use type attribute as:
Injecting simple values
Suppose we have a Student class as:
Student.java
package di.constructor;
public class Student{
int age;
String name;
//Constructor 1
Student(String name, int age){
this.age = age;
this.name = name;
}
void showDetails(){
System.out.println("Name="+name+" Age="+age);
}
}
public class Student{
int age;
String name;
//Constructor 1
Student(String name, int age){
this.age = age;
this.name = name;
}
void showDetails(){
System.out.println("Name="+name+" Age="+age);
}
}
Here student class has a constructor with two arguments.
To provide the values for these arguments following code will be used in xml file.
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
<bean id="student1" class="di.constructor.Student">
<constructor-arg value="Alex"/>
<constructor-arg value="23"/>
</bean>
</beans>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
<bean id="student1" class="di.constructor.Student">
<constructor-arg value="Alex"/>
<constructor-arg value="23"/>
</bean>
</beans>
Note that one argument age is of type int but in xml file we are passing it as String. Spring will convert this automatically to int type. Spring can convert a value supplied in string format to basic types such as int, long, String, boolean, etc.
To run this example write another class:
Test.java
package di.constructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test{
public static void main(String args[]){
ApplicationContext appContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Student stud = (Student) appContext.getBean("student1");
stud.showDetails();
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test{
public static void main(String args[]){
ApplicationContext appContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Student stud = (Student) appContext.getBean("student1");
stud.showDetails();
}
}
Output:
Name=Alex Age=23
Injecting reference to other beans
Instead of providing simple values of basic types like int, String, boolean etc. we can also provide references to other beans as values in <constructor-arg> tag.
Suppose Student class has a another constructor in addition to the previous one:
//Constructor2
Student(Student s){
this.name = s.name;
this.age = s.age;
}
Student(Student s){
this.name = s.name;
this.age = s.age;
}
Then for this we have to use following code in xml file:
<bean id="student1" class="di.constructor.Student">
<!--Will invoke constructor 2 with single argument-->
<constructor-arg ref="student2"/>
</bean>
<bean id="student2" class="di.constructor.Student">
<!--Will invoke constructor 1 with two arguments-->
<constructor-arg value="Mark"/>
<constructor-arg value="17"/>
</bean>
<!--Will invoke constructor 2 with single argument-->
<constructor-arg ref="student2"/>
</bean>
<bean id="student2" class="di.constructor.Student">
<!--Will invoke constructor 1 with two arguments-->
<constructor-arg value="Mark"/>
<constructor-arg value="17"/>
</bean>
Note that here we have used ref attribute instead of value attribute in <constructor-arg> tag of bean with id student1.
No-arg constructor
Suppose we do not provide any <constructor-arg> tag in the bean definition of Student as:
<beans ...>
<bean id="student1" class="di.constructor.Student"/>
</beans>
then which constructor of Student will be called - Constructor1 or Constructor2?<bean id="student1" class="di.constructor.Student"/>
</beans>
It will give an error:
Caused by: java.lang.NoSuchMethodException: di.constructor.Student.<init>()
This is because it will then try to invoke a no-argument constructor in Student class but we have not provided any such constructor yet. So add following constructor to Student class:
// Constructor 3 : no-arg constructor-->
Student(){
name = "Garry";
age = 24;
}
Student(){
name = "Garry";
age = 24;
}
Now if you run the program it will print:
Name=Garry Age=24
Using 'name', 'type' and 'index' attributes.
Note the order of arguments of Student's constructor.
//Constructor 1
Student(String name, int age){
...
}
Student(String name, int age){
...
}
Now suppose in xml file if we provide their values in opposite order :
<bean id = "student" class="di.constructor.Student">
<!-- providing age first-->
<constructor-arg value="23"/>
<constructor-arg value="Alex"/>
</bean>
<!-- providing age first-->
<constructor-arg value="23"/>
<constructor-arg value="Alex"/>
</bean>
This will give error. To resolve this we can use name attribute of <constructor-arg> tag as:
<bean id="student" class="di.constructor.Student">
<constructor-arg name="age" value="23"/>
<constructor-arg name="name" value="Alex"/>
</bean>
<constructor-arg name="age" value="23"/>
<constructor-arg name="name" value="Alex"/>
</bean>
Or we can also use index attribute as:
<bean id="student" class="di.constructor.Student">
<constructor-arg index="1" value="23"/>
<constructor-arg index="0" value="Alex"/>
</bean>
<constructor-arg index="1" value="23"/>
<constructor-arg index="0" value="Alex"/>
</bean>
Note that first argument of constructor is considered as at index 0.
Or we can aslo use type attribute as:
<bean id="student" class="di.constructor.Student">
<constructor-arg type="int" value="23"/>
<constructor-arg type="String" value="Alex"/>
</bean>
<constructor-arg type="int" value="23"/>
<constructor-arg type="String" value="Alex"/>
</bean>
I would like to know your comments and if you liked the article then please share it on social networking buttons.
No comments:
Post a Comment