Java Basics - Dependency Injection

dimitrilc 2 Tallied Votes 222 Views Share

Introduction

When following tutorials on Daniweb, you might have run into one that requires knowledge about Dependency Injection as a prerequisite. People might also sometimes use the term Inversion of Control interchangeably with DI.

These terms are related to one another, but they are not the same. In this article, we will learn the basics of Dependency Injection and I will attempt to explain it in the simplest way possible.

Goals

At the end of the article, you would have learned:

  1. What dependency injection is.

Prerequisite Knowledge

  1. Basic Java.

Dependency Injection vs. Inversion of Control

IoC refers to a programming principle where a framework calls your code instead of your code interacting with a particular device by itself. Because the framework is directly interacting with the device, but not your code, the control has been inverted from you to the framework.

An example of this is the Android Activity class, where you are mostly responsible for defining what to do at lifecycle callbacks, such as onStart(), or onPause(). The Android system is responsible for calling your code when your App is started or paused.

The opposite of IoC is when you open a database connection yourself, execute whatever queries that you need, and then closing the connection. You are in control here and no framework is calling your code.

DI is a little different to IoC because with DI, you are only giving up the control of the creation of dependencies. You simply state what you need, and then an injector will provide the dependencies to you. You do not need to know what an injector is in this basic article. Furthermore, you can simply think of them as classes that provide dependencies to your class.

Common types of Dependency Injection

The three most common types of DI are:

  1. Constructor injection: the DI framework or injector will provide dependencies to the constructor on object creation.

     class Foo {
    
        //Foo depends on Bar
        private final Bar bar;
    
        //Injector will provide an instance of Bar
        //on creation of Foo
        Foo(Bar bar){
            this.bar = bar;
        }
     }
  2. Setter injection: The DI framework or injector class will call the setter method, providing the dependency after the object has been created.

     class Foo {
        private Bar bar;
    
        public void setBar(Bar bar) {
            this.bar = bar;
        }
     }
  3. Field Injection: The DI framework or injector will set the value for the field directly via reflection. This type of DI incur a performance cost, so certain DI frameworks, such as Dagger 2, do not support it.

     class Foo {
        private Bar bar;
     }

There is also another type of DI called Interface Injection, but I have not seen it used widely, so I would not cover it here.

Manual Dependency Injection

Sometimes, Manual DI might be brought up. This refers to you creating your own dependency container, putting you in charge of managing the shared dependencies among your classes. This approach makes sense if you do not want to bring in a DI framework as a dependency, or maybe your app is small. Since this topic deserves its own tutorial, I will have to discuss in a separate article.

Most of the time, I prefer to use a DI framework because I would rather focus on providing features in my application instead of re-inventing the wheel.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.