Dagger2 is a dependency framework. The points that separate it from other dependency frameworks are:
- 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.
- 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.Inject
against 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.
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