Dagger

0

Dagger2 is a dependency framework. The points that separate it from other dependency frameworks are:

  1. It uses generated code, containing factory classes that knows the type of instances to be created and, how and where to inject them. Since it doesn’t use reflection overall performance is good.
  2. The generated code appears to be hand-written thus improving traceability.

In this article we will introduce the basic components which the dagger framework relies on for dependency injection.

We will first look into the pom.xml that contains the dagger dependencies and the plugin that helps to generate the code that dagger depends on to create instance and inject. dagger.internal.codegen.ComponentProcessor is the annotation processor that generates the code based on the annotations.

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.javarticles.dagger</groupId>
	<artifactId>daggerExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>daggerExample</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>23.0</version>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
			<version>2.11</version>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
			<version>2.11</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.7.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<annotationProcessors>
						<annotationProcessor>dagger.internal.codegen.ComponentProcessor</annotationProcessor>
					</annotationProcessors>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Dagger Components

Dagger @Component contains the modules defined by @Module which in turn contains the instance providers defined by @Provider. In order to inject a dependency we need to use annotation javax.inject.Injectagainst the constructors and fields we are interested in. The dependency instance must have been defined as one of the provider. If not dagger can create instance for you if there is a no-argument constructor with the @Inject annotation. We look into both these aspects in our simple example.

Dagger Components

Lets first define our main application classes and the dependencies using @Inject.
Class Foo depends on Bar and BarHolder.

Foo:

package com.javarticles.dagger.daggerExample;

import javax.inject.Inject;

public class Foo {
    private Bar bar;
    @Inject
    BarHolder barHolder;

    @Inject
    public Foo(Bar bar) {
        this.bar = bar;
    }

    Bar getBar() {
        return bar;
    }
    
    public BarHolder getBarHolder() {
        return barHolder;
    }
    
    @Override
    public String toString() {
        return "Foo (" + bar + ")";
    }
}

Bar:

package com.javarticles.dagger.daggerExample;

import javax.inject.Inject;

public class Bar {
    @Inject
    public Bar() {       
    }
    
    @Override
    public String toString() {
        return "Bar";
    }
}

BarHolder:

package com.javarticles.dagger.daggerExample;

public class BarHolder {
    private Bar actualBar;

    public BarHolder(Bar actualBar) {  
        this.actualBar = actualBar;
    }
    
    @Override
    public String toString() {
        return "BarHolder(" + actualBar + ")";
    }
}

BarModule:

package com.javarticles.dagger.daggerExample;

import dagger.Module;
import dagger.Provides;

@Module
public class BarModule {
    @Provides BarHolder provideBarHolder(Bar bar) {
        return new BarHolder(bar);
    }
}

AppComponent:

package com.javarticles.dagger.daggerExample;

import dagger.Component;

@Component(modules= {BarModule.class})
public interface AppComponent {
    Foo foo();
}

AppComponent is the main component that wires the dependencies together. It depends on module BarModule to provide the dependencies. DaggerAppComponent is the dagger generated implementation of AppComponent that knows how to wire the dependencies.
App:

package com.javarticles.dagger.daggerExample;

/**
 * Simple app to test injection via dagger
 */
public class App 
{
    public static void main( String[] args )
    {
        AppComponent appComponent = DaggerAppComponent.create();
        System.out.println(appComponent.foo());
        System.out.println(appComponent.foo().getBarHolder());
    }
}

Output:

Foo (Bar)
BarHolder(Bar)

Class Foo has two fields, one is of type Bar and the other is of type BarHolder. Field barHolder is annotated with @Inject so dagger will inject the instance using the provider method provideBarHolder() defined in BarModule.
Class Foo has the an argument of type Bar in its constructor. This argument must be explicitly injected or the class the argument belongs to must have @Inject for the dragger framework to take control.

Download source code

This was an example about dagger.

You can download the source code here: daggerExample.zip

About Author

Ram’s expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring.
You can reach him at [email protected]

Comments are closed.