Dependency Injection – Part 2

Dependency Injection: image of a syringe

Last week I introduced the concept of dependency injection. This week we look at how we implement DI in code.

Implementing Dependency Injection

Dependency injection has three common implementation mechanisms:

Constructor Injection

Constructor Injection provides the class’s dependencies in its constructor(s). We declare a constructor or a set of constructors taking the dependencies as arguments. The DI container passes these dependencies to the class when it instantiates it. Constructor injection is usually used for mandatory (usually immutable) dependencies. Constructor injection is 100% portable between containers.

Setter Injection

Setter Injection provides the class’s dependencies using JavaBean-style setter methods. The DI container uses these setters to inject the dependencies. Setter injection is usually used for optional dependencies. This lets us create reconfigurable objects which can be changed later at runtime by calling the setters. Setter injection is 100% portable between containers.

Field Injection

Field injection is done using annotations on fields. The container uses the Reflection API to access the fields directly. The dependency values are injected directly into the fields of the class when the container instantiates it. Field injection is very easy to use, but is usually container-specific and not portable.

Dependency Injection: Code Examples

In the previous post I used the example of an InvoiceProcessor that has a dependency on a DatabaseManager. How does a container wire the dependency? We need to write the class in a way that supports constructor, setter and/or field injection.

Constructor Injection

public class InvoiceProcessor {
// dependency
private DatabaseManager dbManager;
// constructor
public InvoiceProcessor (DatabaseManager dbManager) {
// set the DatabaseManager after data validation code
this.dbManager = dbManager;
}
// other code ...
}

Setter Injection

public class InvoiceProcessor {
// dependency
private DatabaseManager dbManager;
// setter
public setDatabaseManager (DatabaseManager dbManager) {
// set the DatabaseManager after data validation code
this.dbManager = dbManager;
}
// other code ...
}

Field Injection

public class InvoiceProcessor {
// The container injects a DatabaseManager instance
// directly into the field.

@Inject (from JSR 330)
private DatabaseManager dbManager;
// other code ...
}

We could replace the @Inject annotation with any of the following annotations, depending on the DI container we’re using:

  • @Resource (from JSR 250)
  • @Named (from JSR 299)
  • @Autowired (Spring specific)

A JEE application server only supports the annotations that are part of the JEE specification (JSRs 250, 299, 330). Spring has its own annotations and supports all the JEE annotations as well.

Wrapping Up

In all three examples above, the DI container creates an instance of DatabaseManager (or one of its subclasses). It then passes this instance to the InvoiceProcessor at runtime. The InvoiceProcessor doesn’t know or care how the DatabaseManager was created. All it knows is that it has a properly initialised DatabaseManager object to use.

I haven’t shown any container code – that’s too specific for this post. The DI container can create an InvoiceProcessor instance based on instructions in a deployment descriptor, an XML file, or some other mechanism.

The important point is that we must write our classes in a way that will allow the container to inject the dependency.

Using constructor/setter injection, our classes are always decoupled from the DI container. If we decide to use field injection, we limit ourselves to a specific container.

Join me next week for the last article in this short series on dependency injection.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.