Java EE CDI Dependency Injection (@Inject) tutorial

25 May 2013
By Gonçalo Marques
In this tutorial you will learn about the different ways to use @Inject annotation in order to perform Dependency Injection with Java EE CDI.

Introduction

Java EE CDI makes primarily use of the @Inject annotation in order to perform Dependency Injection of managed beans into other container managed resources. In this tutorial we will cover the different available strategies to perform dependency injection in a CDI environment.

This tutorial considers the following environment:

  1. JDK 1.7.0.21
  2. Weld 1.1.10

Weld is the CDI reference implementation

Constructor dependency injection

Constructor dependency injection

public class SomeBean {
  
  private final Service service;

  @Inject
  public SomeBean(Service service){
    this.service = service;
  }

}

When the CDI container is instantiating a bean of type SomeBean it will look for the default (no arguments) constructor and use it to create the bean instance. The exception to this rule is when we have another constructor annotated with @Inject. If this is the case, the container will use the annotated constructor instead and will inject the dependencies that are passed as constructor arguments.

In the above sample it will fetch a Service instance and inject into the SomeBean annotated constructor.

Note: Remember that it may only exist a single constructor annotated with @Inject

Field dependency injection

Field dependency injection

public class SomeBean {
  
  @Inject
  private Service service;

}

In this case when the container is initializing a bean of type SomeBean it will inject the correct Service bean into the field, even if it is private, without the need of any setter method.

Initializer methods dependency injection

Initializer methods dependency injection

public class SomeBean {
  
  private Service service;
  
  @Inject
  public void setService(Service service) {
    this.service = service;
  }

}

In this case when the container is initializing a bean of type SomeBean it will call all methods that are annotated with @Inject and inject the dependencies as method arguments.

The @Any qualifier

In order to provide fully loosely coupled applications we usually inject interfaces into managed resources. What if we have multiple bean implementations for a given interface? We may inject them all into a managed bean using the @Any qualifier along with the CDI Instance interface:

The @Any qualifier

public class SomeBean {
  
  @Inject
  public void listServiceImplementations(
      @Any Instance<Service> serviceList) {

    for(Service service : serviceList){
      System.out.println(service.getClass().getCanonicalName());
    }

  }
}

The @Any qualifier instructs the container that this injection point may be satisfied by any available dependency, so the container injects them all. If we have multiple interface implementations and we inject only one - without making any kind of disambiguation - the container will complain and fail to initialize the component. We will see about dependency disambiguation in other tutorial.

Injection into Producer methods

Producer method arguments may also be injected by the CDI container. Please see Java EE CDI Producer methods tutorial.

CDI Proxies

This tutorial will not be complete of we didn't also cover the CDI proxying mechanism. When we inject a managed bean that is created in a scope different than @Dependent - into another managed resource - the CDI container does not inject a direct reference to the injected bean.

For CDI bean scopes please see Java EE CDI bean scopes.

Why does CDI uses proxies? Because if direct bean references were injected it would create problems like thread-safety or concurrent access to managed beans.

Imagine that a Session scoped bean is injected into an Application scoped bean. Since application scoped beans are shared among all clients, if more than one client accessed the application scoped bean simultaneously it would exist a high risk of one client accessing the other's directly referenced session scoped bean.

To work around this problem CDI creates proxies and inject the proxies instead into the injection points. The proxy will then handle the calls to the injected beans and forward the calls to the correct bean instance.

The proxies created by CDI extend the class of the injected bean. Imagine the following scenario:

Application and Session scoped beans

@SessionScoped
public class Service {

  public void doWork() {
    System.out.println("Working...");
  }

}


@ApplicationScoped
public class SomeBean {
  
  @Inject
  private Service service;
  
  public void test(){
    service.doWork();
  }

}

CDI will inject a proxy to the session scoped bean into the application scoped bean. Every call to the session scoped bean will go through the proxy that in turn will redirect the call to the correct session bean instance: the one that belongs to the current HTTP request session.

CDI creates proxies by extending the bean class and overriding all non-private methods. A mere representative illustration of the proxy could be like the following:

Illustrative CDI proxy

public class Service$Proxy$_$$_WeldClientProxy 
  extends Service {

  @Override
  public void doWork() {
    Service instance = // ... resolve bean instance
    instance.doWork();
  }

}

Since CDI proxies are created by extending the bean class there are some CDI restrictions that should come into your mind when we talk about non-dependent bean scopes:

  1. CDI can not inject primitive types
  2. The bean class must have a non-private default constructor
  3. The bean class must not be final and must not have any final methods

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with 8+ years of experience in software development and architecture design. During this period his main focus was delivering software solutions both in banking and telecommunications area. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

He is also the author of the WiFi File Browser Android application: