@Retention(value=RUNTIME)
@Target(value=TYPE)
@Documented
public @interface Component
@Component
prepended with Dagger
. For
example, @Component interface MyComponent {...}
will produce an implementation named
DaggerMyComponent
.
Every type annotated with @Component
must contain at least one abstract component
method. Component methods may have any name, but must have signatures that conform to either
provision or members-injection contracts.
Provision methods have no parameters and return an injected
or
provided
type. Each method may have a Qualifier
annotation as well. The
following are all valid provision method declarations:
SomeType getSomeType();
Set<SomeType> getSomeTypes();
@PortNumber int getPortNumber();
Provision methods, like typical injection
sites, may use Provider
or
Lazy
to more explicitly control provision requests. A Provider
allows the user
of the component to request provision any number of times by calling Provider.get()
. A
Lazy
will only ever request a single provision, but will defer it until the first call to
Lazy.get()
. The following provision methods all request provision of the same type, but
each implies different semantics:
SomeType getSomeType();
Provider<SomeType> getSomeTypeProvider();
Lazy<SomeType> getLazySomeType();
Members-injection methods have a single parameter and inject dependencies into each of the
Inject
-annotated fields and methods of the passed instance. A members-injection method
may be void or return its single parameter as a convenience for chaining. The following are all
valid members-injection method declarations:
void injectSomeType(SomeType someType);
SomeType injectAndReturnSomeType(SomeType someType);
A method with no parameters that returns a MembersInjector
is equivalent to a members
injection method. Calling MembersInjector.injectMembers(T)
on the returned object will
perform the same work as a members injection method. For example:
MembersInjector<SomeType> getSomeTypeMembersInjector();
While a members-injection method for a type will accept instances of its subtypes, only
Inject
-annotated members of the parameter type and its supertypes will be injected;
members of subtypes will not. For example, given the following types, only a
and
b
will be injected into an instance of Child
when it is passed to the
members-injection method injectSelf(Self instance)
:
class Parent {
@Inject A a;
}
class Self extends Parent {
@Inject B b;
}
class Child extends Self {
@Inject C c;
}
Component implementations are primarily instantiated via a generated
builder. An instance of the builder
is obtained using the builder()
method on the component implementation.
If a nested @Component.Builder
type exists in the component, the builder()
method will return a generated implementation of that type. If no nested
@Component.Builder
exists, the returned builder has a method to set each of the
modules() and component dependencies() named with the
lower camel case version of the module
or dependency type. Each component dependency and module without a visible default constructor
must be set explicitly, but any module with a default or no-args constructor accessible to the
component implementation may be elided. This is an example usage of a component builder:
public static void main(String[] args) {
OtherComponent otherComponent = ...;
MyComponent component = DaggerMyComponent.builder()
// required because component dependencies must be set
.otherComponent(otherComponent)
// required because FlagsModule has constructor parameters
.flagsModule(new FlagsModule(args))
// may be elided because a no-args constructor is visible
.myApplicationModule(new MyApplicationModule())
.build();
}
In the case that a component has no component dependencies and only no-arg modules, the
generated component will also have a factory method create()
.
SomeComponent.create()
and SomeComponent.builder().build()
are both valid and
equivalent.
Each Dagger component can be associated with a scope by annotating it with the scope annotation. The component implementation ensures that there is only one provision of each scoped binding per instance of the component. If the component declares a scope, it may only contain unscoped bindings or bindings of that scope anywhere in the graph. For example:
@Singleton @Component
interface MyApplicationComponent {
// this component can only inject types using unscoped or @Singleton bindings
}
In order to get the proper behavior associated with a scope annotation, it is the caller's
responsibility to instantiate new component instances when appropriate. A Singleton
component, for instance, should only be instantiated once per application, while a
RequestScoped
component should be instantiated once per request. Because components are
self-contained implementations, exiting a scope is as simple as dropping all references to the
component instance.
While there is much utility in isolated components with purely unscoped bindings, many applications will call for multiple components with multiple scopes to interact. Dagger provides two mechanisms for relating components.
The simplest way to relate two components is by declaring a Subcomponent
. A
subcomponent behaves exactly like a component, but has its implementation generated within
a parent component or subcomponent. That relationship allows the subcomponent implementation to
inherit the entire binding graph from its parent when it is declared. For that reason,
a subcomponent isn't evaluated for completeness until it is associated with a parent.
Subcomponents are declared by listing the class in the Module.subcomponents()
attribute of one of the parent component's modules. This binds the Subcomponent.Builder
within the parent component.
Subcomponents may also be declared via a factory method on a parent component or subcomponent. The method may have any name, but must return the subcomponent. The factory method's parameters may be any number of the subcomponent's modules, but must at least include those without visible no-arg constructors. The following is an example of a factory method that creates a request-scoped subcomponent from a singleton-scoped parent:
@Singleton @Component
interface ApplicationComponent {
// component methods...
RequestComponent newRequestComponent(RequestModule requestModule);
}
While subcomponents are the simplest way to compose subgraphs of bindings, subcomponents are tightly coupled with the parents; they may use any binding defined by their ancestor component and subcomponents. As an alternative, components can use bindings only from another component interface by declaring a component dependency. When a type is used as a component dependency, each provision method on the dependency is bound as a provider. Note that only the bindings exposed as provision methods are available through component dependencies.
Modifier and Type | Optional Element and Description |
---|---|
java.lang.Class<?>[] |
dependencies
A list of types that are to be used as component
dependencies.
|
java.lang.Class<?>[] |
modules
A list of classes annotated with
Module whose bindings are used to generate the
component implementation. |
public abstract java.lang.Class<?>[] modules
Module
whose bindings are used to generate the
component implementation. Note that through the use of Module.includes()
the full set of
modules used to implement the component may include more modules that just those listed here.public abstract java.lang.Class<?>[] dependencies