Monday, 28 September 2015

What is Dependency Injection in Spring

Dependency injection is one of the core concept of Spring and it is imperative to understand "What is Dependecy Injection" and how Spring uses it. It is hard to explain it in theory so I'll take a simple example and go step by step to explain what Dependency injection is.

As the name suggests Dependency injection means injecting the dependencies but what does that mean? When we create any application there are many classes in it which depend on each other to execute some business logic. In that case any object which needs other objects to do its work, is responsible for getting those dependencies itself.

Let's see it with an example -

Suppose there is a payment service through which you can execute several kind of payments - cash payment, credit card payment, debit card payment etc.

So you create an interface which every Payment class should implement -

public interface IPayment {
    void executePayment();
}

And you create one of the class CashPayment for processing cash payments.

public class CashPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Cash Payment"); 
 }
}

Then you create an interface for your Payment Service class and the PaymentService class itself -

public interface IPayService {
 void performPayment();
}
public class PayServiceImpl implements IPayService {
 private CashPayment cashPayment;
 PayServiceImpl(){
  this.cashPayment = new CashPayment();
 }

 public void performPayment() { 
  cashPayment.executePayment();
 }
}

Now you can see the problems here in the PaySerivceImpl class -

  • It is creating its own CashPayment reference, so it is tightly coupled only to cash payment functionality. How about Credit card payment or debit card payment or any other mode of payment?
  • We started well with creating separate classes for separate behaviours and using interfaces but then we introduced CashPayment class itself in PaySerivceImpl, with that one step separation of concern is gone!
  • What if we need to unit test this class? We can't mock its dependencies (i.e. the Payment class) as PayServiceImpl class is tightly coupled to CashPayment class.

Now you know the hazards of tightly coupled dependencies but at the same time you also know that dependencies will always be there in any applications, Objects will refer to each other in order to execute the business logic.

So, how about getting those dependencies injected in your code by some other class, in that case objects won't be creating their dependencies themselves but the dependencies will be injected into the objects. Again let's see the same example with some changes to facilitate dependency injection.

How about writing your PayServiceImpl class like this -

public class PayServiceImpl implements IPayService {
 private IPayment payment;
 
 PayServiceImpl(IPayment payment){
  this.payment = payment;
 }
 public void performPayment() {
  payment.executePayment();
 }
}

Just compare it with the previous implementation of PayServiceImpl class.

  • There it was tightly coupled with the specific implementation (CashPayment) of the IPayment interface. In this class it is not tightly coupled with any specific implementation.
  • In this class specific implementation is given (injected) in the constructor of the class.
    IPayService payService = new PayServiceImpl(new CashPayment());
    payService.performPayment();
    
    This will call the CashPayment implementation.
    payService = new PayServiceImpl(new CreditPayment());
    payService.performPayment()
    
    This will call the CreditPayment implementation.
  • Here the code is loosely coupled as PayServiceImpl is not tied to any specific implementation, here it only knows the interface which can easily be swapped by specific implementation at run time as we just saw in point 2

CreditPayment implementation

public class CreditPayment implements IPayment {
    public void executePayment() {
 System.out.println("Performing credit payment");
    }
}

How Spring comes in the picture

Now we know what dependency injection is and how objects can be injected rather than created by the object itself. So how about having a framework which will manage these associations for you and inject dependencies too. That's where Spring comes in the picture.

Though there are many ways in Spring to manage these associations (term used in Spring is wiring) here I'll given an example with XML configuration, that should give you an idea how dependency injection works through Spring.

<?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-4.0.xsd">
 
 <!-- defining CashPayment bean -->
  <bean id="cashPaymentBean" class="org.netjs.prog.CashPayment" />
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
      <constructor-arg ref="cashPaymentBean" />
  </bean>
</beans>

Here it can be seen that CashPayment and PayServiceImpl are declared as beans in spring XML configuration. In PayServiceImpl bean, reference of CashPayment is passed as a constructor argument. With that configuration Spring framework will take care of wiring the associations and injecting the dependencies needed by an object.

If you want to test and see how it is done this class can be used -

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App 
{
    public static void main( String[] args )
    {   
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
        IPayService bean = (IPayService) context.getBean("paymentBean");
        bean.performPayment();
        context.close();
    }
}

In Spring framework, Dependency Injection exits in two major types:

You can mix both, Constructor-based and Setter-based DI but it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies.

That's all for this topic What is Dependency Injection. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Constructor-based dependency injection in Spring
  2. Setter-based dependency injection in Spring
  3. Spring example program using XML configuration
  4. Spring example program using JavaConfig and Annotations
  5. Spring example program using automatic configuration
  6. How to inject prototype scoped bean in singleton bean

You may also like -

>>>Go to Spring tutorial page

6 comments:

  1. Very good explanation of dependency injection in Spring.

    ReplyDelete
  2. Clear definition with nice example... Way to go!!!

    ReplyDelete
    Replies
    1. Thanks for your encouraging words!

      Delete
  3. I didnt understand the puporse:

    This:
    bean id="paymentBean" class="org.netjs.prog.PayServiceImpl"
    constructor-arg ref="cashPaymentBean"
    bean

    is the same of this:
    IPayService payService = new PayServiceImpl(new CashPayment());

    if we want to pay with CreditPayment we have to change the ref in xml.
    How to it dynamically with Spring

    I'm sorry, noob question but i'd like to understand.

    ReplyDelete
  4. Basically, instead of having your objects creating a dependency or asking a factory object to make one for them, you pass the needed dependencies in to the object externally, and you make it somebody else's problem. This "someone" is either an object further up the dependency graph, or a dependency injector (framework) that builds the dependency graph.

    ReplyDelete