Sunday, March 4, 2012

Dependency Injection


1)       Dependency Injection:

Spring framework has the capability to inject the dependencies to java objects. DI is also known as Inversion of Control (IOC). I have just learnt the Dependency Injection in spring. Although there are lots of articles on this topic but my intention is to let people who are starting to learn spring framework, understand the concepts of DI.
Bookish Definition: Dependency Injection is the dependencies of java objects managed by a container so that Object can concentrate on its functionality rather than for its dependencies. When applying DI, objects are given their dependencies at the creation time by some external entity that coordinates each object in the system. In other words, dependencies are injected into objects.
Simple definition: DI can be simply told as decoupling of work (encouraging the loose coupling).The only thing we need to understand is an object's dependencies should be on interfaces and not on "concrete" objects, when possible. (A concrete object is any object created with the keyword new.) Hence we cannot use new keyword.
Work: Display the names of Indian states.
Class A: Handles the logic part.
Class B: Handles query part from DB.
Class C: Interface
Now Class A does not bother how Class B got the results whether it got it by doing simple query or by writing stored procedures or PL\SQL, what it needs is query results. It will take that results through the interface (Class C) and display the names of the Indian states.
This is somewhat similar to the Hollywood Principle: "Don't call us, we'll call you”. i.e. You implement the interfaces, you get registered. You get called when the time is right.
I don’t want you to confuse further as it’s easy to understand the topic with the help of an example.
Code example:
In the below example, what we are going to do is to find it out which Object Relational Mapping we are using in the code. We will create an Interface, one main class, two different Orm techniques class and then a service class. We will inject the ORM through the controller bean xml and displayOrm method which will display the Orm tool being used.

<pre class="brush: js">
<div id="tweets">
                Orm.java
----------------
package com.sk;
 public interface Orm {
                                public String getOrmName();
}
               
</div>
</pre>

                          
The IBatis and Hibernate class implements Orm interface and getOrmName method.

<pre class="brush: js">
             <div id="tweets">
IBatis.java
----------------
package com.sk;
public class IBatis implements Orm {
                                @Override
                                public String getOrmName() {
                                                return "I'm using iBatis";
                                }
}

Hibernate.java
-------------------
package com.sk;
public class Hibernate implements Orm {
                @Override
                public String getOrmName() {
                                return "I'm using Hibernate";
                }
}

</div>
            </pre>


We have a OrmService class that tells the developer which Object Relational mapping is being used. The OrmService class holds reference to the Orm.

<pre class="brush: js">
 <div id="tweets">
OrmService.java
---------------------
package com.sk;
public class OrmService {
                private Orm orm = new Hibernate();
                public void displayOrm(){
                                System.out.println(orm.getOrmName());
                }
}
</div>
</pre>

At last we will create OrmTool class which will display the Object Relational mapping is being used.

<pre class="brush: js">
 <div id="tweets"> 
OrmTool.java
-------------------
package com.sk;
public class OrmTool {
                public static void main(String[] args) {
                                OrmService ormService = new OrmService();
                                ormService.displayOrm();
                }
}
</div>
</pre>
As you can see it is pretty simple, here we create an instance of the OrmService class and call the displayOrm() method. This method will display the ORM being used.
Let's have a look at the class diagram of this example. The green arrows indicate generalization and the blue arrow indicates association.



 















As you can see this architecture is tightly coupled. We create an instance of the Orm in the OrmService class in the following way to display Hibernate.

 <pre class="brush: js">
<div id="tweets">
private Orm orm = new Hibernate();
</div>
</pre>
To make our Orm display iBatis we need to make modifications to the OrmService class like this.

<pre class="brush: js">
<div id="tweets">
private Orm orm = new IBatis();
</div>
</pre>

So it is tightly coupled. Now let’s see how we can avoid this by using the Dependency Injection design pattern. The spring framework provides powerful container to manage the components. The container will inject the required dependencies. We can inject the dependencies using the setter or constructor injection (this is explained in the later section).
Here we will see how we can do this using the setter injection.

 <pre class="brush: js">
<div id="tweets">
OrmService.java
---------------------
package com.sk;
public class OrmService {
                Orm orm;
                public void setOrm(Orm orm) {
                                this.orm = orm;
                }
                public void displayOrm(){
                                System.out.println(orm.getOrmName());
                }
}

</div>
</pre>

The value for the Orm will be set using the setOrm() method. The Orm object is never instantiated in the OrmService class, but still we access it. Usually this will throw a NullPointerException, but here the containers will instantiate the object for us, so it works fine.
After making all the changes, the class diagram of the example look like this. 




 















The container comes into picture and it helps in injecting the dependencies. The bean configuration is done in the Controller-beans.xml file.

<pre class="brush: js">
<div id="tweets">
Controller-beans.xml
-------------------------------------------
<?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="hibernate" class="com.sk.Hibernate"></bean>
                <bean id="iBatis" class="com.sk.IBatis"></bean>
                <bean id="ormService" class="com.sk.OrmService">
                                <property name="orm">
                                                <ref local="hibernate"/>
                                </property>
                </bean>
</beans>

</div>
                 </pre>

We define each bean using the bean tag. The id attribute of the bean tag gives a logical name to the bean and the class attribute represents the actual bean class. The property tag is used to refer the property of the bean. To inject a bean using the setter injection you need to use the ref tag.
Here a reference of Hibernate is injected to the Orm bean. Now when we want to change the ORM to IBatis, the only change we need to do is, to change the bean reference in the ref tag.

<pre class="brush: js">
<div id="tweets">
<bean id="ormService" class="com.sk.OrmService">
                <property name="orm">
                                <ref local="iBatis"/>
                </property>
</bean>

</div>
                 </pre>

2) Types of DI

2.1 Constructor Injection

2.2 Setter Injection

       2.1   Constructor Injection :
    Constructor-based DI is affected by invoking a constructor with a number of arguments, each     representing a dependency.
        <pre class="brush: js">
        <div id="tweets">
a)      Through XML
<bean id="ormService" class="com.sk.OrmService">
        <constructor-arg type="int" value="7500000"/>
        <constructor-arg type="java.lang.String" value="42"/>
</bean

b)      Through Java config :
public class OrmService {

    // the OrmService has a dependency on a Orm
    private Orm orm;

    // a constructor so that the Spring container can 'inject' a Orm
    public OrmService (Orm orm) {
        this. orm = orm;
    }
    // business logic that actually 'uses' the injected Orm is omitted...
           
           </div>
           </pre>

     2.2   Setter Injection
Setter-based DI is realized by calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.

            <pre class="brush: js">
            <div id="tweets"> 
a)      Through XML :
<bean id="ormService" class="com.sk.OrmService">
    <property name="name" value="sk"/>
</bean> 
b)      Through Java config
public class OrmService {

    // the OrmService has a dependency on the Orm
    private Orm orm;

    // a setter method so that the Spring container can 'inject' a Orm
    public void setOrm(Orm orm) {
                                this.orm = orm;
                }

    // business logic that actually 'uses' the injected Orm is omitted...
}

</div>
                </pre>

3. XML or Java Configuration

                The wiring up of the dependencies with the objects can be done using Java code and XML both. Some people prefer java code and some prefer xml configuration. I think it is a simpler to work with Java code. But then for beginners and business people, xml is better as it is easily configurable. This thought is divided and may be in some other article I will try to cover it.


No comments:

Post a Comment