Friday, April 14, 2023

Inversion of Control and Dependency Injection design pattern with real world Example - Spring tutorial

Inversion of Control and Dependency Injection is a core design pattern of Spring framework. IOC and DI design pattern is also a popular design pattern interview question in Java. As the name suggest Inversion of control pattern Inverts responsibility of managing the life cycle of the object e.g. creating an object, setting their dependency etc from application to a framework, which makes writing Java application even more easy. The programmer often confused between IOC and DI, well both words used interchangeably in Java world but Inversion of Control is a more general concept and Dependency Injection is a concrete design pattern.

Spring framework provides two implementations of IOC container in the form of Application Context and BeanFactory which manages the life-cycle of bean used by Java application. As you may know, necessity is the mother of invention, it benefits to first understand the problem solved by IOC and Dependency Injection design pattern. This makes your understanding more clear and concrete.

We have touched basics of Dependency Injection and Inversion of control in our article 10 OOPS and SOLID design principles for Java programmer and this Java article tries to explain it by taking a real-life example of Service based architecture popular in enterprise Java development. 

In this Spring or design pattern tutorial, we will first see the normal implementation of AutditService class, a class in this example that provides auditing in enterprise Java application and then use of dependency Injection. This will allow us to find out problems and how they are solved by the Dependency injection design pattern. . 

Btw, In order to best understand design patterns, you need to work out some scenarios, examples, etc. It's best to get this kind of knowledge as part of your work but even if you don't get there, you can supplement them by joining a comprehensive course like e Design Patterns in Java and doing some object-oriented software design exercises. 

Also there are multiple way to inject dependency in spring e.g. Setter Injection or Constructor Injection, which uses setter method and constructor for injecting dependency, see Setter injection vs Constructor injection  to find out when to use them.




Inversion of Control and Dependency Injection design pattern

Any way let’s back to core concept of Inversion of Control and dependency Injection design pattern. Look at below implementation of an AuditService whose job is to store every audit messages into database. This is one of the simplest kind of auditing Service required in Enterprise Java application.

/**
 * Java Service class which provides auditing functionality by storing
 * auditing message into persistent.
 */

public class AuditServiceImpl implements AuditService{

    private AuditDAO auditDao = new AuditDAO();
     
    @Override
    public boolean audit (String message) {
       return auditDao.store(message);
    }
 
}


In first glance this implementation looks perfect but there are three major problem with this implementation:

1) Every AuditServiceImpl has its own copy of AuditDAO which is an expensive object as it wraps a database connection with in. It make no sense to create separate instances of AuditDAO, if you can share one between multiple AuditService.

2) AuditServiceImpl is closely coupled with AuditDAO as its creating instance of AuditDAO using new() operator. If you change the constructor of AuditDAO this code will be broken. Because of this coupling its difficult to replace AuditDAO with better implementation.

3) There is no easy way to test audit() method which is dependent on auditDAO. Since you can not mock AuditDAO you have to rely on actual implementation and if AuditDAO is an environmental dependent object which it is as it connect to different database on a different environment, your Junit test case may pass in some environment and may fail in other environments.

By the way, if you are new to Spring framework then I also suggest you join a comprehensive and up-to-date course to learn Spring in depth. If you need recommendations, I highly suggest you take a look at Spring Framework 5: Beginner to Guru, one of the comprehensive and hands-on course to learn modern Spring. It' also most up-to-date and covers Spring 5.

How dependency injection works in Spring Framework





What is Dependency Injection concept?

What is IOC and DI design pattern in Spring tutorial with example
Dependency Injection is a design pattern on which dependency of the object (in this case AuditDAO is a dependency for AuditServiceImpl Object) is injected by the framework rather than created by Object itself. Dependency Injection reduces coupling between multiple objects as its dynamically injected by the framework. 

One of the implementations of DI is Inversion of Control (IOC) on which framework like Spring controls object’s dependency. There are mainly two types of Dependency Injection: Constructor Injection and Setter Injection.

In Constructor Injection, the dependency of Object is injected using constructor, while in Setter Injection, Dependency is provided by the setter method

Both have there pros and cons. Constructor DI allows the object to be created in complete state and follows the principle of the fully functional object while Setter DI allows object to be created without its dependency. which may result in an incomplete object if dependency is not available. 

This answers one of the famous spring interview question "when do you use Setter injection and Constructor Injection in Spring".  Another benefit of Setter Dependency Injection is readability since Spring is configured with xml configuration file and setter injection is provided with bean property which is much easier to read and understand than constructor injection which doesn't state the property.



AuditServiceImpl using Dependency Injection

Now we will see How Dependency Injection solves all three problems we have listed with the above implementation of AuditService. here is a new implementation of AuditService with setter dependency injection.

public class AuditServiceImpl implements AuditService{

    private AuditDAO auditDao;

    public void setAuditDao(AuditDAO AuditDao) {
        this.AuditDao = AuditDao;
    }
 
    @Override
    public boolean audit (String message) {
       return auditDao.store(message);
    }
 
}

1. Since AuditDAO is injected here its possible to share single AuditDAO (an expensive object) between multiple AuditService.

2. Since AuditServiceImpl is not creating an instance of AuditDAO its no more coupled with AuditDAO and works with any implementation of AuditDAO, thanks to another famous object-oriented design principle “program for interface than implementation".


3. Because AuditDAO is injected by DI at runtime it's easy to test audit() method by providing a mock AuditDAO class. This not only makes testing easier but also independent of environmental changes as you are not using the actual implementation of AuditService.

This was the exact way I learn Dependency Injection and Inversion Of Control design principles. It always helps first to understand the problem and then solution to related to each other. From the above learning we can easily derive advantages or benefits of Dependency Injection in Java application:

1) Reduce coupling
both constructor and setter dependency injection reduce coupling. like in the above example coupling between AuditService and AuditDAO is reduced by using Dependency Injection.

2) Improves testability
Dependency Injection allows to replace the actual object with a mock object which improves testability by writing simple JUnit tests which uses a mock object.

3) Flexibility
This is another advantage which comes as a side benefit of reduced coupling, because of DI you can replace non-performance implementation with a better one later.


That’s all on What is Inversion of control and Dependency Injection design pattern. We have tried to learn this pattern with a real-life example and compares a class that is written using the principle of IOC and DI and without that. IOC and DI easily bring quality in coding. We have seen clear benefits in terms of reducing coupling, improved testability, and Flexibility to change implementation. It’s always good to write code that follows principle of Inversion of Control and dependency Injection and Spring framework by default ensures that.

Further Reading
Spring Master Class - Beginner to Expert
Introduction to Spring MVC 4 By Bryan Hansen
Spring Framework 5: Beginner to Guru
Spring in Action 4th edition by Craig Walls



P. S. - If you want to learn how to develop RESTful Web Service using Spring MVC in depth, I suggest you join the REST with Spring certification class by Eugen Paraschiv. One of the best course to learn REST with Spring MVC. 

12 comments:

  1. I was confused between Inversion of Control and Dependency Injection and looking for exaxt deference between Inversion of Control and Dependency Injection. Your article explains it right for once and all. a Big Thanks

    ReplyDelete
  2. DI is special case of IoC right ?

    ReplyDelete
  3. As the name implies Inversion of control means now we have inverted the control of creating the object from our own using new operator to container or framework. Now it’s the responsibility of container to create object as required. We maintain one xml file where we configure our components, services, all the classes and their property. We just need to mention which service is needed by which component and container will create the object for us. This concept is known as dependency injection because all object dependency (resources) is injected into it by framework.

    ReplyDelete
  4. First you say "Inversion of Control is more general concept and Dependency Injection is a concrete design pattern" and then you say "One of the implementation of DI is Inversion of Control (IOC)".

    Do you even proof read what you write. I find your other posts too full of silly mistakes.

    ReplyDelete
  5. there is a small typo under the setAuditDao method,

    this.AuditDao -> this.auditDao

    ReplyDelete
  6. One of the major advantages of dependency injection is that it can make testing lots easier. Suppose you have an object which in its constructor does something like:

    public SomeClass() {
    myObject = Factory.getObject();
    }

    ReplyDelete
  7. //ICO , DI ,10 years back , this was they way:

    public class AuditDAOImpl implements Audit{

    //dependency
    AuditDAO auditDAO = null;
    //Control of the AuditDAO is with AuditDAOImpl because its creating the object
    public AuditDAOImpl () {
    this.auditDAO = new AuditDAO ();
    }
    }

    Now with Spring 3,4 or latest its like below

    public class AuditDAOImpl implements Audit{

    //dependency

    //Now control is shifted to Spring. Container find the object and provide it.
    @Autowired
    AuditDAO auditDAO = null;

    }


    Overall the control in inverted from old concept of coupled code to the frameworks like Spring which makes the object available. So thats IOC and Dependency injection as you know when we inject the object using Constructor or setters. Inject basically means passing it as argument. In spring we have XML & annotation base configuration where we define beans and pass the dependent object with COnstructor or setter injection style.

    ReplyDelete
  8. Please give a good blog on Restful webservices with programming.

    ReplyDelete
  9. I have been looking for example of DI and IoC for a while and haven't found any as clear as this one. Thanks for taking the time, very well explained.
    One quick question, as in your example you are not using annotations, shouldn't we have to add an applicationContext.xml with a bean for the service and property to this bean for the DAO?

    ReplyDelete
  10. I was looking for proper example of ioc and di.Finally I have found here. Great explanation.

    ReplyDelete
  11. Thanks @Unknown, Happy that you find it useful.

    ReplyDelete
  12. For some reason this website was blocking up to 30% of my processor! Otherwise, I found it pretty useful.

    ReplyDelete