Burak Aktas Software Engineer

Java CDI Dependency Injection Example

CDI (Context and Dependency Injection) is a specification defined in JSR-299. Major aim is loose coupling by dependency injection.In this tutorial we will see how to use CDI Dependency Injection in java with three different ways;

  • Field injection
  • Constructor injection
  • Setter method injection

We are going to use @Inject alongside @Named annotations from CDI of Java EE. @Named annotation is used for giving names for classes which implements the interface, and it is optional. Otherwise, we can specify alternatives and a default bean by @Alternative, and @Default annotations. However, I am going to show them in this tutorial. Moreover, these are the example interface and implementation classes we are going to use.

Notes:

  • @Named annotation is commonly used if there are more than one implementation for an interface. Thus, it provides to give and inject by their names.
  • If there is only one implementation of an interface and @Named annotation is used, then the name of the bean is determined as camelCase style of class name.
  • We can use @Default and @Alternative annotations instead of giving names to them.
  • If there is only one implementation of an interface, compiler will inject it as the default one. So, there is no need to use @Named, @Default or @Alternative annotations.

Important

We have to create an empty beans.xml file in src/main/resources/META-INF if it is a jar application or src/main/webapp/WEB-INF if it is a war application.

<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="

http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

</beans>

AutoService.java

public interface AutoService {
    void getService();
}

BMWAutoService.java

@Named("bmwAutoService")
public class BMWAutoService implements AutoService{

    @Override
    public void getService() {
        System.out.println("You chose BMW auto service");
    }
}

FordAutoService.java

@Named("fordAutoService")
public class Ford implements AutoService{

    @Override
    public void getService() {
        System.out.println("You chose Ford auto service");
    }
}

HondaAutoService.java

@Named("hondaAutoService")
public class HondaAutoService implements AutoService{

    @Override
    public void getService() {
        System.out.println("You chose Honda auto service");
    }
}

AutoServiceCaller.java

public interface AutoServiceCaller {
    void callAutoService();
}

1. Injection Through Fields

Beans are injected through fields.

public class AutoServiceCallerImp implements AutoServiceCaller{

    @Inject
    @Named("bmwAutoService")
    private AutoService bmwAutoService;

    @Inject
    @Named("hondaAutoService")
    private AutoService hondaAutoService;

    @Inject
    @Named("fordAutoService")
    private AutoService fordAutoService;

    @Override
    public void callAutoService() {
        // get bmw's auto service
        bmwAutoService.getService();

        // get ford's auto service
        fordAutoService.getService();

        // get honda's auto service
        hondaAutoService.getService();
    }
}

2. Injection Through Setter Methods

We can also inject our beans via setters

public class AutoServiceCallerImp implements AutoServiceCaller{

    private AutoService bmwAutoService;
    private AutoService hondaAutoService;
    private AutoService fordAutoService;

    @Override
    public void callAutoService() {

        bmwAutoService.getService();
        fordAutoService.getService();
        hondaAutoService.getService();
    }

    @Inject
    public void setBmwAutoService(@Named("bmwAutoService") AutoService bmwAutoService) {
        this.bmwAutoService = bmwAutoService;
    }

    @Inject
    public void setHondaAutoService(@Named("hondaAutoService") AutoService hondaAutoService) {
        this.hondaAutoService = hondaAutoService;
    }

    @Inject
    public void setFordAutoService(@Named("fordAutoService") AutoService fordAutoService) {
        this.fordAutoService = fordAutoService;
    }
}

3. Injection Through Constructor

Finally, beans can be injected through the constructor of the class.

public class AutoServiceCallerImp implements AutoServiceCaller{

    private AutoService bmwAutoService;
    private AutoService hondaAutoService;
    private AutoService fordAutoService;

    @Inject
    public AutoServiceCallerImp(@Named("bmwAutoService") AutoService bmwAutoService,
                             @Named("hondaAutoService") AutoService hondaAutoService,
                             @Named("fordAutoService") AutoService fordAutoService) {

        this.bmwAutoService = bmwAutoService;
        this.fordAutoService = fordAutoService;
        this.hondaAutoService = hondaAutoService;
    }

    @Override
    public void callAutoService() {
        // get bmw's auto service
        bmwAutoService.getService();

        // get ford's auto service
        fordAutoService.getService();

        // get honda's auto service
        hondaAutoService.getService();
    }
}