Enterprise Java

Dependency Injection – The manual way

Dependency injection is a technique that separates behavior from dependency resolution. In simpler words, it allows the developer to define classes with specific functionality that depends on various collaborators, without having to define how reference to these collaborator will be obtained. In that way, decoupling among the various components is achieved and cleaner code is introduced in general. More specifically, instead of hard-coding the dependencies, a component just lists the necessary services and at run-time, an external, independent component will provide access to those services. We should not forget that dependency injection is just a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The reference article for the aforementioned techniques is “Inversion of Control Containers and the Dependency Injection pattern” by Martin Fowler.

For the purpose of injecting dependencies, a number of frameworks has emerged, the most well-known being Spring and Guice (check the JavaCodeGeeks Spring related articles). However, the use of a whole framework for small projects is undoubtedly an overkill. One of our JCG partners, writer of the “Death By Code” blog, has written a small introduction on how to handle dependency injection manually. Let’s see what he has to say…

In another post, “Do I Really Need a Singleton?”, I wrote about the problems introduced by the Singleton design pattern. When the single unique instance is being accessed through the getInstance() method, Singleton acts as a global variable in disguise and introduces tight coupling and unwanted dependencies. I have received two immediate questions from my readers:

Should a Singleton be used only with Dependency Injection Framework?
If accessing a Singleton through getInstance() creates tight coupling, creating an instance of any other class through new() also causes tight coupling. So, how should an object be created maintaining loose coupling?

As per my understanding, Dependency Injection is the answer for both the questions. But, that does not mandate the usage of a framework. Dependency Injection is a concept first and then a framework. When the application under question is small, we can always meet the needs by injecting dependencies manually, without using any framework like Spring.

In any Java application, we repeatedly encounter with two events:

  • Object creation
  • Interaction between the objects – The business logic

But, usually we mix up both of them which leads to tight coupling and unwanted dependencies which in turn makes the maintenance as well as unit testing a pain. Let me try to explain it using a very simple example:

class MyClass {

 private A a; //A is an interface
 private B b; //B is an interface

 //Object creation within constructor
 MyClass(A a, B b) {  
    a = new AImpl(); //AImpl is the concrete impl of A
    b = new BImpl(); //BImpl is the concrete impl of B
 }

 //Application logic lies within this method
 public void doSomething() {
    //Do A specific thing
    //Do B specific thing
    C c = new CImpl(); //Object creation within the method.
    //Do C specific thing
 }
}

The Problems with this class is:

  1. It has not been able to separate out the the object creation from the business logic resulting in a tight coupling.
  2. Here “programing to the implementation” has been done, not to interface. Tomorrow, if different implementations of A, B or C is required, the code inside the class has to be changed.
  3. Testing MyClass would require testing of A, B, C first.

Let me try to fix the problem:

class MyClass {

 private A a;
 private B b;
 private C c;

 MyClass(A a, B b, C c) {
    //Only Assignment
    this.a = a;
    this.b = b;
    this.c = c;
 }

 //Application Logic
 public void doSomething() {
    //Do A specific thing
    //Do B specific thing
    //Do C specific thing
 }
}

//The Factory
class MyFactory {
 public MyClass createMyClass() {
    return new MyClass(new AImpl(), new BImpl(), new CImpl());
 }
}

class Main {
 public static void main(String args[]) {
    MyClass mc = new MyFactory().createMyClass();
    mc.doSomething();
 }
}

What has been achieved here:

1. Constructor does not have a new():
Objects are not being created within the constructor of MyClass. The constructor is simply being used for field (A, B, C) assignments. Here the constructor asks for the dependencies as parameters, but does not create them (And that is the Simplest definition of dependency injection). However, simple Collection objects like ArrayList, HashMap OR value/leaf objects like Person/Employee (i.e the objects within the application which in turn does NOT create other objects) CAN BE created within the Constructor. Constructor should not be used for any other operation like I/O, thread creation etc.

As a thumb rule, any object should hold references ONLY to other objects whom it needs directly to get it’s work done (This is called the Law of Demeter). For example, if MyClass needs some other class called X, MyClass’ constructor should directly ask for X. It should NOT ask for some other factory F which can return an instance of X. Violation of “Law of Demeter” would result in unwanted dependency between MyClass and F. So, if you find more than one Dot (.) operator be careful – something illegal is happening there.

2. Factory (MyFactory) is taking care of object creation and wiring:
All the new operators (90%-99%) should belong to the factory. It should take care of entire object graph creation for the application and also of relating (wiring) different objects based on their declared dependencies (e.g MyClass needs A, B, C etc). It should not contain anything more – not any other logic (No I/O, thread creation etc).

Tomorrow if C starts depending on something else called D, only C and the factory would be impacted, not the entire object graph (C would have to introduce an overloaded constructor and factory would have to incorporate the object instantiation plus the object wiring related changes).

For a large application of course there may be multiple factories. Here, thumb rule is one factory should instantiate all the objects with same life span.

3. Object creation is separate from the business logic:
MyClass is now a Business Logic Holder. It does not have any new(). Even, it does not have any knowledge about the concrete implementations it is using for the business logic (i.e it knows about A but not about AImpl – “program to interface and not to implementation”).

You must have started thinking that I started this discussion with the context of Singleton. How does the manual dependency injection take care of a Singleton? How does it create a Singleton (minus the tight coupling, hidden dependency etc) and access it when needed? Surprisingly, we already have three Singletons in our example – AImpl, BImpl, CImpl. If the factory takes care of creating only one instance of a Class (by invoking new() only once), its a Singleton. Isn’t it? Then the factory may pass that unique instance in the form of dependencies to all other objects those need it.

4. So, where are we? 
MyClass, the business logic holder needs A, B and C for it’s business. It does not create them but asks for them (the dependencies). The factory (MyFactory) creates those dependencies and wire them to MyClass. But, who creates, the factory? Of course, the main method (the application launcher :-)). Let me repeat the story again, the main method first instantiates the factory, the factory in turn instantiates the object graph, each Object declares their dependencies and finally the main method itself sets the ball rolling – launch the application by invoking doSomething() of MyClass, ie. the objects starts talking to each other executing the usual business.

Let me repeat it once more: Create the factory, create the application using the factory and then start the application! For a large scale application the same thing can be achieved with a Dependency Injection framework like Spring, Google Guice etc. Of course they will come with lot of other benefits, in addition. But, for a small to medium scale application, dependency injection can be hand crafted making the app loosely coupled, more maintainable and of course unit test friendly.

Related Articles :
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Radek
Radek
10 years ago

Correct me if I’m wrong, but in line 07 of your first listing MyClass(A a, B b), these two arguments a and b are completely useless, aren’t they? It’s a detail but for this particular topic (DI) it can be a little bit misleading…

Java_FAN
Java_FAN
10 years ago

Really THANK YOU. MAY GOD BLESS YOU.. THAT WAS AWESOME.. Helped me a lot..

Enrico Dela Cruz
Enrico Dela Cruz
8 years ago

I suggest to make a static call on creataMyClass() method.
Instead of this :
MyClass mc = new MyFactory().createMyClass();
proposed code :
MyClass mc = MyFactory.createMyClass();

Himanshu
Himanshu
8 years ago

Yes, similar to Enrico I feel that createMyClass() method should be static, so that no need to use new to create MyClass object.

Piyush Munjal
Piyush Munjal
6 years ago

Thanks for the solution but i want to know how to do it in mvc and webapi project.

I have a project of mvc architecture and another project of web api and i want to apply dependency injection in web api and access that web api through mvc controller. so how to inject dependency manually in this project.

Thanks and hope to get solution ASAP
Piyush Munjal

Back to top button