Spring Dependency Injection

Dependency Injection is a technique to wire objects together in a flexible way. So, it also called wiring between objects. It plays a vital role in gluing classes together and at the same time keeping them independent.

Consider an application for the simplest shopping as shown in the class diagram as below:


Figure: Class Diagram for Shopping Store

The application provided is a very simple application that has a ProductService class, which implements the IProductService interface. Similarly, IProductRepository interface is implemented by ProductRepository class and contains a list of Products. Application.java calls the getProduct() method on ProductService class which in turn calls findOne() method on ProductRepository class and to get the Product of given productNumber.

Java implemented the code of the above application without spring is at my Github repository inside ProductApplication folder.

You can clone the repository and run the file Application.java by right-clicking on it and selecting Run As  Java Application to provide the following output:

[ Product number = 423, name = Plasma TV, price = 992.55]

[ Product number = 239, name = DVD player, price = 315.0]

This is a pretty straightforward application with simple object creation and method invocation.


Different way’s to “wire” two objects together

  1. Instantiate an object directly
  2. Use an interface
  3. Use a factory object
  4. Use Spring Dependency Injection

In all of first three methods, we do have none or just a little flexibility to change the code in one class without affecting another class. Only the dependency injection provides full flexibility to change one class irrespective of another class.

Now, in order to use the dependency injection, we’ve to use any of framework. We’re going to use Spring Framework here.

So, now import the given ProductApplicationDI project (in the directory given applications) into IntelliJ IDEA or Eclipse or any IDE you prefer for Java Application development. Then add all JAR files in the directory libraries to the classpath of this application. Then you should be able to run the file Application.java with the same output as mentioned above.

In order to configure our application with Spring framework, I’ve used XML. 

Look at Application.java. I’ve changed the application in such way that Application.java no longer instantiates ProductService but instead retrieves this object from the Spring context. In other words, the following code:

IProductService productService = new ProductService();

has been changed to:

ApplicationContext context = new ClassPathXmlApplicationContext("springconfig.xml");
IProductService productService = context.getBean("productService", IProductService.class);

Here, the first line creates an ApplicationContext based on springconfig.xml and the second line gets the bean with id=“productService” from the ApplicationContext.

The bean declaration with id productService is:

<bean id="productService" class="com.eShop.service.ProductService">
    <property name="productRepository" ref="productRepository" />

<bean id="productRepository" class="com.eShop.repository.ProductRepository" />

The attribute productRepository is configured in XML and the Spring framework takes care that productRepository references the ProductRepository object.

How Dependency Injection works?

Dependency Injection takes place in a two-step.

Step 1. Spring instantiates all beans in the XML configuration file

spring dependency injection 1Step 2. Spring then connects the productRepository attribute to the ProductRepository instance

dependency injection 2This is also setter-based DI.


Advantages of DI

  1. Flexibility: it is easy to change the wiring between objects without changing code

If we want to add new class MockProductRepo as below,

public class MockProjectRepo implements IProductRepository {
    public Product findOne(int productNumber) {
        return new Product(423,"Mock Object",123.00);

and wire it to ProductService, then we just need to change at springconfig.xml as

<bean id="productService" class="com.eShop.service.ProductService">
    <property name="productRepository" ref="productRepository" />

<bean id="productRepository" class="com.eShop.repository.MockProjectRepo" />

If you notice carefully, then you see that you just need to change the class name.

      2. Unit testing becomes easier

3. Code is clean

When to use DI?

  1. When an object references another object whose implementation might change 
    • You want to plug-in another implementation
  2.  When an object references a plumbing object 
    • An object that sends an email
    • A DAO object
  3.  When an object references a resource 
    • For example a database connection