Dependency Injection using Spring Framework

What is dependency injection?

Dependency injection (DI) is the method to create needed dependencies or look them up somehow without doing it in the dependent code. You do not create your objects but describe how they should be created. Then, it is the job of the container (like Spring container) to actually inject those dependencies when it creates the bean. This is fundamentally the inverse of the bean itself being in control of instantiating or locating its dependencies on its own using direct construction of classes. Hence DI is also referred to as Inversion of Control (IoC).

Spring supports two types of dependency injection:
  • Setter Dependency Injection:
Dependency is provided through setter methods as per Java Bean style.

  • Constructor Dependency Injection:
The dependency is injected via constructor arguments.

What is a bean?

Bean is a typical java bean with a unique id. A bean is simply an object that is instantiated, assembled and otherwise managed by a Spring IoC container. In spring there are basically two types of beans:
  •  Singleton
One instance of the bean is created and referenced each time it is requested.
  • Prototype (non-singleton)
New bean created each time. It is same as new ClassName().
What is a bean definition?

The bean definition defines a bean for Spring to manage. The Key attributes of a bean definition are:
  •  class (required):
            Fully qualified java class name.

  •  id:
                            The unique identifier for this bean
  • configuration:
Singleton, init-method, etc.
  • constructor-arg
 Arguments to pass to the constructor at creation time.
  • property:
 arguments to pass to the bean setters at creation time.
  •  Collaborators:
other beans needed in this bean (dependencies), specified in property or constructor –arg.

Bean definitions are typically defined in an XML file called configuration metadata.

Configuration metadata

The configuration metadata is nothing more than how you (as an application developer) inform the spring container as to how to instantiate, configure, and assemble the objects in your application.
This configuration metadata is typically supplied in a simple and intuitive XML format. When using XML-based configuration metadata, you write bean definitions for those beans that you want the Spring IoC container to manage, and then let the container do its stuff.
XML-based metadata is by far the most commonly used form of configuration metadata. It is not however the only form of configuration metadata that is allowed.
Spring configuration consists of at least one bean definition that the container must manage, but typically there will be more than one bean definition. When using XML-based configuration metadata, these beans are configured as elements inside a top-level element.
These bean definitions correspond to the actual objects that make up your application. Typically you will have bean definitions for your service layer objects, your data access objects (DAOs), presentation objects such as Struts Action instances.
Below is an example of the basic structure of XML-based configuration metadata:

<?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-2.5.xsd">   
      <bean id="..." class="...">   
           <!-- collaborators and configuration for this bean go here -->   
      </bean>   
      <bean id="..." class="...">   
           <!-- collaborators and configuration for this bean go here -->  
       </bean>   
      <!-- more bean definitions go here -->   
 </beans>  



The container:
Container is responsible for containing and otherwise managing the aforementioned beans.
The BeanFactory interface is the central IoC container interface in Spring. Its responsibilities include instantiating or sourcing application objects, configuring such objects, and assembling the dependencies between these objects.
There are a number of implementations of the BeanFactory interface that come supplied straight out-of-the-box with Spring. The most commonly used BeanFactory implementation is the XmlBeanFactory class. The XmlBeanFactory takes the XML configuration metadata and uses it to create a fully configured system or application.
BeanFactory is not used directly often.Often it is seen as an ApplicationContext . The ApplicationContext is a complete superset of the BeanFactory, and any description of BeanFactory capabilities and behavior is to be considered to apply to the ApplicationContext as well.

 

ApplicationContext instantiation for web applications:

As opposed to the BeanFactory, which will often be created programmatically, ApplicationContext instances can be created declaratively using for example a ContextLoader. You can also create ApplicationContext instances programmatically using one of the ApplicationContext implementations. The ContextLoader mechanism comes in two flavors: the ContextLoaderListener and the ContextLoaderServlet.

You can register an ApplicationContext using the ContextLoaderListener as follows:


<context-param>   
      <param-name>contextConfigLocation</param-name>   
      <param-value>/WEB-INF/daoContext.xml </param-value>   
 </context-param>   
 <listener>   
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
 </listener>   
 <!-- or use the ContextLoaderServlet instead of the above listener   
 <servlet> <servlet-name>context</servlet-name>   
      <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>   
      <load-on-startup>1</load-on-startup>   
 </servlet>   
 -->  

The listener inspects the 'contextConfigLocation' parameter. If the parameter does not exist, the listener will use /WEB-INF/applicationContext.xml as a default.

The ContextLoaderServlet can be used instead of the ContextLoaderListener. The servlet will use the 'contextConfigLocation' parameter just as the listener does.


Some examples:

Setter-based DI Example:
First, an example of using XML-based configuration metadata for setter-based DI. Below is a small part of a Spring XML configuration file specifying some bean definitions.

<bean id="exampleBean" class="examples.ExampleBean">  
  <!-- setter injection using the nested <ref/> element -->  
  <property name="beanOne"><ref bean="anotherExampleBean"/></property>  
  <!-- setter injection using the neater 'ref' attribute -->  
  <property name="beanTwo" ref="yetAnotherBean"/>  
  <property name="integerProperty" value="1"/>  
 </bean>  
 <bean id="anotherExampleBean" class="examples.AnotherBean"/>  
 <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>  


public class ExampleBean {  
   private AnotherBean beanOne;  
   private YetAnotherBean beanTwo;  
   private int i;  
   public void setBeanOne(AnotherBean beanOne) {  
     this.beanOne = beanOne;  
   }  
   public void setBeanTwo(YetAnotherBean beanTwo) {  
     this.beanTwo = beanTwo;  
   }  
   public void setIntegerProperty(int i) {  
     this.i = i;  
   }    
 }  

 As you can see, setters have been declared to match against the properties specified in the XML file.

Constructor-based DI Example
Below  is an example of using constructor-based DI.
<bean id="exampleBean" class="examples.ExampleBean">  
  <!-- constructor injection using the nested <ref/> element -->  
  <constructor-arg>  
   <ref bean="anotherExampleBean"/>  
  </constructor-arg>  
  <!-- constructor injection using the neater 'ref' attribute -->  
  <constructor-arg ref="yetAnotherBean"/>  
  <constructor-arg type="int" value="1"/>  
 </bean>  
 <bean id="anotherExampleBean" class="examples.AnotherBean"/>  
 <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>  

public class ExampleBean {  
   private AnotherBean beanOne;  
   private YetAnotherBean beanTwo;  
   private int i;  
   public ExampleBean(  
     AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {  
     this.beanOne = anotherBean;  
     this.beanTwo = yetAnotherBean;  
     this.i = i;  
   }  
 }  
As you can see, the constructor arguments specified in the bean definition will be used to pass in as arguments to the constructor of the ExampleBean.
Injecting Collections:
The <list/><set/>, <map/>, and<props/> elements allow properties and arguments of the Java Collection type List, Set, Map, and Properties, respectively, to be defined and set.
<bean id="moreComplexObject" class="example.ComplexObject">
  <!-- results in a setAdminEmails(java.util.Properties) call -->
  <property name="adminEmails">
   <props>
     <prop key="administrator">administrator@example.org</prop>
     <prop key="support">support@example.org</prop>
     <prop key="development">development@example.org</prop>
   </props>
  </property>
  <!-- results in a setSomeList(java.util.List) call -->
  <property name="someList">
   <list>
     <value>a list element followed by a reference</value>
     <ref bean="myDataSource" />
   </list>
  </property>
  <!-- results in a setSomeMap(java.util.Map) call -->
  <property name="someMap">
   <map>
     <entry>
       <key>
         <value>an entry</value>
       </key>
       <value>just some string</value>
     </entry>
     <entry>
       <key>
         <value>a ref</value>
       </key>
       <ref bean="myDataSource" />
     </entry>
   </map>
  </property>
  <!-- results in a setSomeSet(java.util.Set) call -->
  <property name="someSet">
   <set>
     <value>just some string</value>
     <ref bean="myDataSource" />
   </set>
  </property>
 </bean>

Note that the value of a map key or value, or a set value, can also again be any of the following elements:
bean | ref | idref | list | set | map | props | value | null
  
XML-based configuration metadata shortcuts:
The <property/>, , and elements all support a 'value' attribute which may be used instead of embedding a full element.
Therefore, the following:

<property name="myProperty">   
  <value>hello</value>   
  </property>   
 <constructor-arg>   
  <value>hello</value>   
  </constructor-arg>  
 <entry key="myKey">   
  <value>hello</value>   
  </entry>  

are equivalent to:

<property name="myProperty" value="hello"/>
 <constructor-arg value="hello"/> 
 <entry key="myKey" value="hello"/>

The and elements support a similar shortcut 'ref' attribute which may be used instead of a full nested element. Therefore, the following:


  <ref bean="myBean"> 
  </property> 
  <constructor-arg> 
  <ref bean="myBean"> 
  </constructor-arg> 

... are equivalent to:

<property name="myProperty" ref="myBean"/> 
  <constructor-arg ref="myBean"/>

Finally, the entry element allows a shortcut form to specify the key and/or value of the map, in the form of the 'key' / 'key-ref' and 'value' / 'value-ref' attributes. Therefore, the following:

<entry> 
  <key> 
   <ref bean="myKeyBean" /> 
  </key> 
  <ref bean="myValueBean" /> 
  </entry>
is equivalent to:

 <entry key-ref="myKeyBean" value-ref="myValueBean"/  
  </entry>   

Note however that the shortcut form is equivalent to a element; there is no shortcut for >.





Comments

Unknown said…
Helpful material for beginners.
Rajan said…
Awesome tutorial.

I have never found such a complete combination of code and description before.

I think You should write another post about the best way to start using Spring in a web application.
BoharaG said…
Thank you so much for your feedback and suggestion. I will definitely try my best to come up with new post.

Popular posts from this blog

Old Questions for Big Data Technologies at Institute of Engineering(IOE), Tribhuvan University, Nepal

Unable to evaluate the selected expression while debugging Java project in eclipse

Install the Windows Subsystem for Linux