Menu

Dagger 2 has Components

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 a UserAuthenticator 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 the HttpServletRequest. An Android app's screenGraph would have a binding for the current Context.

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.