Much of the Dagger vs. Guice comparison is about code generation vs. reflection. But they're also different in how they ask you to structure your application...
Guice
Guice apps are built with these fundamental abstractions:
- Multiple injection points: dependencies, being injected.
- Multiple bindings: dependencies, being provided.
- Multiple modules: a collection of bindings that implement a feature.
- One injector: a collection of modules that implement an application.
And then there's Guice scopes:
- Unscoped: a new instance for each injection. Unscoped objects have the same lifetime of whatever injects them. Business logic classes like an
SmsMessageValidator
should be unscoped. - Custom-scoped: your business logic controls how injected instances are shared. For example,
@RequestScoped
gives you a place to share the state of an HTTP request. Context-dependent classes like aUserAuthenticator
should be custom-scoped. - Singleton-scoped: one instance for the entire application. Shared resources like a
DatabaseConnectionPool
should be singleton-scoped.
Dagger 1
Dagger 1.x's fundamentals are similar:
- Multiple injection points: same.
- Multiple bindings: same.
- Multiple modules: same.
- Multiple object graphs: a collection of modules that implement a scope.
Dagger doesn't have custom scopes. Instead, we layer multiple object graphs.
- One root object graph contains all of the application-wide stuff. Like the
DatabaseConnectionPool
. - Multiple custom object graphs add context. For example, a web app's
requestGraph
would have a binding for theHttpServletRequest
. An Android app'sscreenGraph
would have a binding for the currentContext
.
The object graphs can be layered. An Android app might have an appGraph
extended by an onboardingFlowGraph
, itself extended by an usernameScreenGraph
. Each graph has access to the bindings of the graph it extends, plus the bindings its modules introduce.
Unfortunately, Dagger 1.0 badly screwed up its scope names, and it's my fault. The @Singleton
annotation is used for both root graphs and custom graphs, so it's tricky to figure out what the actual scope of a thing is.
Dagger 2
Dagger 2 shares its predecessor's fundamentals:
- Multiple injection points: same.
- Multiple bindings: same.
- Multiple modules: same.
- Multiple components: same as Dagger 1.x's ObjectGraph.
Unlike the ObjectGraph
and the Injector
, a component is something you define yourself. It also fixes the scoping problems. Components define their own scope names, so the UsernameScreenComponent
can have a @UsernameScreen
scope. It's more direct.
Learn more about Dagger 2 from Jake Wharton's Dependency Injection with Dagger 2 Devoxx talk. Then get the code from GitHub.