Archive

Archive for September 15, 2012

Inversion of Control – Dependency Injection explained in simple terms

September 15, 2012 3 comments

Inversion of Control – Dependency Injection:

Instead of Object creating its dependencies, let container create and inject into Object. Control is being inverted from Object to Container.

Encapsulation says “The Caller should know its dependencies”

IOC  says “The Caller should know its dependency interfaces”

If the caller doesn’t know its dependencies and knows only interfaces, we can give any of the class to the Object.  Will explain with an example

Let’s Say we have a

package com.java2practice;
public class UsersListFromDB{
     public void printUsers(){
System.out.println(“printing users from database”);
     }
}

 

And UsersView to use the UsersListFromDB,

package com.java2practice;
public class UsersView{
 private UsersListFromDB userListFromDB = new UsersListFromDB();
 public void printUsers(){
      userListFromDB.printUsers();
 }
}

Now create a client program to access the UsersView.java

package com.java2practice;
public class UsersViewTest{
 public static void main(String[] args){
      UsersView usersView = new UsersView();
      usersView.printUsers();
 }
}

If we use like this, the object  UsersListFromDB is tightly coupled with UsersView. If we want to show UsersListFromExcel it won’t be possible.

For this we need to create an interface called

public interface UsersList{
       public void printUsers();
}

And make the UsersListFromDB, UsersListFromExcel implement the UsersList like below

public class UsersListFromDB implements UsersList{
       public void printUsers(){
System.out.println(“users list printing from database”);
       }
}

public class UsersListFromExcel implements UsersList{
       public void printUsers(){
System.out.println(“users list printing from excel”);
       }
}

Now we can change our UsersView class to

public class UsersView{
       private UsersList userList = new UsersListFromDB();
       public void printUsers(){
userList.printUsers();
       }
}

This concept is called interaface referencing. One of the object oriented principle Program to interface not program to class”

But still our problem is not solved, with out changing the UsersView we can not add UsersListFromExcel

Now We will try with Factory Design pattern

public class UsersFactory{
       public UsersList getUsersList(){
                 return new UsersListFromDB();
       }
}

In the UsersView.java we need to call this UsersFactory to get the appropriate object.

public UsersView{
       UsersList usersList = new UsersFactory().getUsersList();
       public void printUsers(){
usersList.printUsers();
       }
}

Now the client program will look like this


public class UsersViewTest{
       public static void main(String[] args){
              UsersView usersView = new UsersView();
              usersView.printUsers();
       }
}

This is more elegant and with out touching UsersView.java file we can switch to UsersListFromExcel  or UsersListFromDB by changing UsersFactory.

But still we need to change the UsersFactory.

With spring IOC our UsersView.java will look like this

public class UsersView{
       private UsersList usersList;
       public void setUsersList(UsersList usersList){
              this.usersList = usersList;
       }
       public void printUsers(){
             usersList.printUsers();
       }
}

That’s it, we don’t need to bother about instantiating the UsersList interface with its implemented classes.

To tell the container about our Java classes we need to write configuration file.

Bean-config.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-3.0.xsd">

      <bean id="usersListFromDB" class="com.java2practice.UsersListFromDB"/>
      <bean id="usersListFromExcel" class="com.java2practice.UsersListFromExcel/">
      <bean id="userView">
<property ref=” usersListFromDB” />
      </bean>
</beans>

We have to write our client program to use all these:

public class UesrsViewTest{
       public static void main(String[] args){
              ApplicationContext context = new ClassPathXmlApplicationContext("bean-config.xml");
              UsersView usersView = (UsersView)context.getBean(“userView”);
              usersView.printUsers();
       }
}

Here ApplicationContext will read the bean configuration file and accordingly it will inject the dependencies into the UsersView.java

When we are calling context.getBean(“userView”) it will return UsersView with dependencies injected into it.

If we want to use UsersListFromExcel, just we need to change in configuration file

Then the out put will be “printing users from excel file”

Advertisements
Categories: Spring