The most profound feature of the Spring framework is its ability to provide dependencies of a class
by itself. Definately, it needs to know which all properties or Objects are to be set in a particular class property. This concept is called as Spring dependency injection.
To tell this, Spring provides various ways like creating an XML file or a PROPERTIES file that contains the bean definitions.Of these ways, the most commonly used way is to write an XML file where we define the classes and its properties that we want Spring to instantiate with the properties values already injected.
To understand Spring dependency injection in more detail, lets say we have two java classes Foo and Bar like:
package basicinjection;
public class Foo {
private String name;
public Foo() { }
public Foo(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
package basicinjection;
public class Bar {
private String name;
private int age;
private Foo foo;
public Bar() {}
public Bar(String name,int age) {
this.name = name;
this.age = age;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void processFooName(){
System.out.println("Name in Injected Foo is: "+foo.getName());
}
@Override
public String toString() {
return "Bar has name = "+this.name+" and age = "+this.age;
}
}
Now to instantiate the above classes, one way is to do the usual new operator like new Foo() or new Bar() OR we can use the spring dependency injection to instantiate these classes and set the properties accordingly. So as discussed earlier, lets create an XML file that describes these two classes we want it to instantiate for us.
<?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-3.0.xsd"> <bean id="foo" class="basicinjection.Foo" scope="prototype"> <constructor-arg index="0" value="Cleopatra"></constructor-arg> </bean> <bean id="bar" class="basicinjection.Bar"> <constructor-arg type="int" value="26" /> <constructor-arg type="java.lang.String" value="Arthur" /> <property name="foo" ref="foo"></property> </bean> </beans>
The "bean" tag is used to define a class which we want Spring framework to instantiate for us. Now to tell which properties of this class will be set, we can use any of the two ways highlighted in the xml file i.e line no 8 and 13. These two techniques together are called as dependency injection and can be categorized as:
There is one another type of Spring dependency injection that is called as Method Injection that we will discuss some other time.
In the above xml file for the first bean, we are telling Spring to instantiate Foo class using Constructor Injection. A constructor can have n number of arguments, and to help Spring identify where to inject which value we have used the index attribute. So now this Foo bean definition states that, Spring should call the suitable constructor with the value at the first argument set to "Cleopatra". And it would internally do something like:
Foo f = new Foo("Cleopatra");
For the second bean definition, we have told Spring that find a suitable constructor where arguments of type int and String are taken as input irrespective of the order and create an Object for me. Based on your need you can use index or type or both attribute to specify constructor arguments. Line no 13 shows the Setter injection, where we say that, to inject the value of this property call its setter method. We have used the "ref" attribute here that means to inject this property with a bean whose Id matches this value. So finally for this bean, something of this sort will happen at the Spring side:
Bar b = new Bar("Arthur",26);
b.setFoo(f);
Now we have all the raw material ready, so lets call upon the Spring framework to do its job. Following is our main method class:
package basicinjection;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFooBar {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"basicinjection/springbasic.xml");
Bar bar = applicationContext.getBean("bar", Bar.class);
bar.processFooName();
System.out.println(bar.toString());
/*
* if a single definition of a class type exists, then u can get the
* instance by this way also. No need to specify Id
*/
Foo foo = applicationContext.getBean(Foo.class);
System.out.println(foo.getName());
}
}
Spring's ClassPathXmlApplicationContext is the commonly used object that hold the information of all the beans that it instantiates. It requires the classpath relative path of the xml file which contains the bean definitions. Once this object is created, we can call its getBean method to get the instantiated object of any definition we provided in the xml file. In the above example we get the Bar Object by its Id specified in bean in the xml file. And since we have mentioned that an object of foo will be injected into it and its name and age properties also set, so when you try to print these values you will successfully get everything set in its right place.
Download Source