Inversion of Control – Dependency Injection explained in simple terms
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”
Inversing of control from developer to an external program in order to create instances and assign references for our java objects is called Dependency injection.
As a java developer, whatever we code [or write] is nothing but handling the control. Taking the control from main method, we move the control with our code in order to serve our requirement. Usually we ask the control to create some instances and invoke required methods on them. Deepening on our requirement we may ask it to hold the execution for some time or execute another set of instructions etc. which is called as threading mechanism. Let’s avoid discussing it here. The objective of IOC is to relieve the developer from the responsibility of creating the objects which makes our code tightly coupled.
Simply to say, instead of creating objects from our code we ask another program to do that and assign the references to our variables. Whenever we are talking about the external program which is apart from our code, the best and easy way of communication to it is through XML files. This is grandly accepted practise in industry for many projects starting from small scale projects to large scale enterprise applications. Using XML files will avoid recompilation of the code which is preferably good news to the deployment team. Because we can’t anticipate all the consequences that arise once we re-build the system for some small modification.
Here we are configuring an external program to create and inject [or assign] references to our objects. We can define this in an XML file.
Finally what I wanna say is, Inversion of Control is a design pattern which allows us to have a provision to configure our system through some XML files for creating objects and assigning appropriate references.
Thanks Arun, your explanation is very clear…
Glad for it dude….