Support free tutorials









vogella training Training Books



Using dependency injection in Java - Introduction - Tutorial

Lars Vogel

Version 2.2

17.05.2012

Revision History
Revision 0.1 14.01.2010 Lars
Vogel
Moved general explanation of dependency injection into own article
Revision 0.2 - 2.2 23.01.2010 - 17.05.2012 Lars
Vogel
bug fixes and enhancements

Dependency injection (DI)

This article describes the concept of dependency injection from a Java perspective.


Table of Contents

1. What is dependency injection?
2. Using annotations to describe dependencies
3. Where can values be injected?
4. Order in which injection is done
5. Java and dependency injection frameworks
6. Support this website
6.1. Thank you
6.2. Questions and Discussion
7. Links and Literature
7.1. Source Code
7.2. Spring Links

1. What is dependency injection?

The general concept behind dependency injection is called Inversion of Control. A class should not configure its dependencies statically but should be configured from outside.

Dependency injection is a concept which is not limited to Java. But we will look at dependency injection from a Java point of view.

A Java class has a dependency on another class if it uses an instance of this class. For example a class which accesses a logger service has a dependency on this service class.

Ideally Java classes should be as independent as possible from other Java classes. This increases the possibility of reusing these classes and to be able to test them independently from other classes.

If the Java class directly creates an instance of another class via the new operator, it cannot be used (and tested) independently from this class and this is called a hard dependency. The following example shows a class which has no hard dependencies.

package com.example.e4.rcp.todo.parts;

import java.util.logging.Logger;

import org.eclipse.e4.core.services.events.IEventBroker;

public class MyClass {
  
  Logger logger;
  
  public MyClass(Logger logger) {
    this.logger = logger;
    // write an info log message
    logger.info("This is a log message.")
  }
} 

Note

Please note that this class is just a normal Java class, there is nothing special about it, except that it avoids direct object creation.

Another class could analyze the dependencies of a class and create an instance of the class, injecting objects into the defined dependency. This can be done via the Java reflection functionality by a framework class usually called the dependency container.

This way the Java class has no hard dependencies, which means it does not rely on an instance of a certain class. This allows you to test your class in isolation, for example by using mock objects.

Mock objects are objects, which act as if they are the real object, but only simulate their behavior. Mock is an English word which means to mimic or imitate.

If dependency injection is used, a Java class can be tested in isolation.

2. Using annotations to describe dependencies

In general different approaches exist to describe the dependencies of a class. The most common approach is to use Java annotations to describe the dependencies directly in the class.

The standard Java annotations for describing dependencies were defined in the Java Specification Request 330 (JSR330). This specification describes the @Inject and @Named annotations.

To decouple Java classes, its dependencies should be fulfilled from the outside. A Java class would simply define its requirements like in the following example:

public class MyPart {

  // import statements left out

  
  @Inject private Logger logger;
  
  // inject class for database access
  @Inject private DatabaseAccessClass dao;
  
  @Inject
  public void createControls(Composite parent) {
    logger.info("UI will start to build");
    Label label = new Label(parent, SWT.NONE);
    label.setText("Eclipse 4");
    Text text = new Text(parent, SWT.NONE);
    text.setText(dao.getNumber());
  }

} 

Note

Please note that this class uses the new operator for the user interface components. This implies that this part of the code is nothing you plan to replace via your tests and that you made the decision to have a hard coupling to the corresponding user interface toolkit.

3. Where can values be injected?

Dependency injection can be performed on:

  • the constructor of the class (construction injection)

  • a field (field injection)

  • the parameters of a method (method injection)

Dependency injection can be performed on static and on non-static fields and methods.

Tip

Avoid using dependency injection for statics as this typically leads to confusion and has the following restrictions:

  • Static fields will be injected after the first object of the class was created via DI, which means not to access the static field in the constructor

  • Static fields should not be marked as final, otherwise the compiler complains about them

  • Static methods are called only once after the first object of the class was created

4. Order in which injection is done

According to JSR330 the injection is done in the following order:

  • constructor injection

  • field injection

  • method injection

The order in which the methods or fields annotated with @Inject are called is not defined by JSR330. You cannot assume that the methods or fields are called in the order of declaration in the class.

Warning

As fields and methods parameters are injected after the constructor is called, you cannot use injected member variables in the constructor.

5. Java and dependency injection frameworks

You can use dependency injection without any additional framework by providing classes with sufficient constructors or getter and setter methods.

A dependency injection framework simplifies the initialization of the classes with the correct objects.

Two popular dependency injection frameworks are Spring and Google Guice.

The usage of the Spring framework for dependency injection is described in Dependency Injection with the Spring Framework - Tutorial.

Also Eclipse 4 is using dependency injection.

6. Support this website

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

6.1. Thank you

Please consider a contribution if this article helped you. It will help to maintain our content and our Open Source activities.

6.2. Questions and Discussion

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

7. Links and Literature

7.1. Source Code

Source Code of Examples

7.2. Spring Links

http://www.springframework.org/ Homepage of the Spring Framework

http://www.vogella.com/tutorials/SpringJDBC/article.html Using the Spring Jdbc Template for Database Access