Wednesday, December 10, 2014

Introduction to Inversion of Control and Dependency Injection

Developers of software strive to reduce dependencies between components in software for various reasons.

This leads to a new problem:
How can a component know all the other components it needs to fulfill its purpose?

Dependency Injection (DI) is a technique that supplies external dependencies to a software component.

An alternative to DI is to hard-code dependencies:
 public class Requestor {  
   public void operation() {  
    DatabaseServiceImplementation dbs = new DatabaseServiceImplementation();  
    dbs.performOperation1();  
   }  
 }  


DI is a form of Inversion of Control (IoC) where the concern being inverted is the process of obtaining the needed dependency:
 public class Requestor {  
   public void operation() {  
    DatabaseServiceInterface dbs = beanFactory.getClass("databaseServices", DatabaseServiceInterface.class);  
    dbs.performOperation1();  
   }  
 }  


This line:
 beanFactory.getClass(“databaseServices”, DatabaseServiceInterface.class);  

returns an interface (or, specification) that contains operations (or, services) that are defined in DatabaseServiceInterface.java.

The name (or, key) used to retrieve this interface is contained in an XML file:
  <bean   
       id="databaseServices"   
       class="com.mycompany.test.ioc.DatabaseServiceImplementation" />   


This mapping tells Spring to instantiate and return an instance of “DatabaseServiceImplementation” whenever the class is called:
 beanFactory.getClass(“databaseServices”, <Class>)   


It is possible to cast “databaseServices” to its concrete implementation as well:
  DatabaseServiceInterface dibs = beanFactory.getClass(  
       "databaseServices",   
       Reimplementation);   

You can also write code like this:
  DatabaseServiceImplementation idbs = beanFactory.getClass(  
       "databaseServices",   
       DatabaseServiceImplementation.class);   

In this case we're using the concrete implementation to instantiate the class, and at first glance there would appear to be little benefit over using an interface. However, we still gain the value of injected dependencies being made available via this approach
In both cases, there is now a dependency to DatabaseServiceImplementation.

Scenarios 3 and 4 are identical to Scenario 1, in terms of introducing a dependency on DatabaseServiceImplementation to the Requestor.

No Interface; No Dependency Injection:

Scenarios 1,3, 4


Coding to an Interface with Dependency Injection:

Scenario 2


The term “Dependency Injection” refers to the container (in this case, Spring) injecting a dependency to a class (in this case, DatabaseServiceImplementation) into the requesting code:
 beanFactory.getBean(<id>, <class>)  

Spring injects a dependency to <id> into the Requestor.

No comments:

Post a Comment