Architecture & DesignWorking with Dependency Injection in Java

Working with Dependency Injection in Java

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The dependency injection pattern, also known as Inversion of Control, facilitates the design and implementation of loosely coupled, reusable, and testable applications. Dependency injection is not limited to the Java programming language; you can use it in other languages as well, such as C#. The basic principle that drives the dependency injection pattern is that the dependencies of a class should not be statically defined but should be configurable from outside of the class. This would promote loose coupling within the components of an application by reducing the cohesion amongst them.

This article presents an overview of the dependency injection pattern, the benefits of this pattern, and how the same can be implemented in Java.

Understanding the Pitfalls of Hard Dependencies

An object may depend on another object; this is also known as object dependency. This behavior is transitive in nature. Consider three objects, namely, A, B, and C. If object A is coupled to object B, and B is in turn coupled to C, then object A is effectively coupled to object C—it is dependent on C.

The coupling between objects can be of two types—tight coupling and loose coupling. When an object is loosely coupled with another object, you can change the coupling with ease; when the coupling is tight, the objects are not independently reusable and hence are difficult to use effectively in unit test scenarios.

Let’s understand this with a simple example. Consider two classes, C1 and C2, where C1 is tightly coupled with C2 and requires it to operate. In this case, C1 is dependent on C2, as shown in the following code snippet:

public class C2
{
   //Some code
}
public class C1
{
   C2 obj = new C2();
   //Some code
}

The tight coupling between the two classes shown above occurs because C1 (which is dependent on C2) creates and contains an instance of the class C2. It’s “tight” because you can eliminate or change the dependency only by modifying the container class (C1). This is where dependency injection fits in.

What Is Dependency Injection? Why Should I Use It?

Dependency injection is a technique that is used to reduce the cohesion or coupling amongst the components in an application. It is a form of the Inversion of Control Pattern that ensures loose coupling between the objects and promotes easier testability and maintainability.

Dependency injection promotes loose coupling and easier testability and maintenance as the dependencies of a class are abstracted and isolated. However, the primary drawback of dependency injection is that wiring instances together can become a nightmare if there are too many instances and many dependencies that need to be addressed. You can know more on dependency injection pattern from this link: http://www.martinfowler.com/articles/injection.html.

Some of the common dependency injection frameworks include the following:

  • Spring
  • Google Guice
  • PicoContainer
  • Dagger

Types of Dependency Injection

Dependencies can be injected by using constructors of a class, fields of a class, or the parameters of a method in a class. So, there are three common forms of dependency injection:

  1. Constructor Injection: This form of dependency injection uses constructors with parameters to inject dependencies. This type of dependency injection is used when the dependencies are mandatory and wouldn’t change throughout the life time of an object.
  2. Field Injection: This type of dependency injection technique uses public fields of a class to inject dependencies. This is much more flexible and the dependencies injected can change over time.
  3. Method Injection: In this form of dependency injection, the parameters of a method are used to inject dependencies. Unlike constructor injection, you can use method injection to re-inject dependencies at a later point of time; in other words, the dependencies injected using this form of dependency injection can be changed if need be.

Well, let’s dig into some code now. The following code snippet illustrates how dependencies can be injected by using constructors in Java. As you can see, there aren’t any hard dependencies here.

public class Test {
   AsyncLogger logger;
   public Test(AsyncLogger logger) {
      this.logger = logger;
      logger.Write("This is a test message.",
         Logtarget.File)
   }

Suggested Readings

Summary

Dependency injection is an approach in which the dependencies of an object are set using an external entity; in other words, the dependencies are configured externally. In this article, we have had a bird’s eye view of dependency injection in Java with code examples wherever appropriate. Happy reading!

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories