译文
标注一个接口或者抽象类从而根据modules
集合生成一个完整的、依赖注入的实现。生成类会以@Component
标注的类名加Dagger前缀命名。例如{@code @Component interface MyComponent {...}}
会产生一个名为DaggerMyComponent
的实现。
1. Component-methods(组件-方法)
每一个使用@Component
标注的类型必须至少包含一个抽象的component
方法。Component
方法名字任意,但必须有符合provision
或者merbers-injection
格式的签名。
1.1 Provision methods(提供类方法)
Provision
方法没有参数,并返回一个injected
或provided
类型。每个方法可能还有一个限定注解。下面这些都是有效的provision
方法声明:
SomeType getSomeType();
Set<SomeType> getSomeTypes();
@PortNumber
int getPortNumber();
Provision
方法,例如典型的injection
位置,可以使用Provider
或Lazy
更加显式地控制provision
请求。一个Provider
允许component
的使用者通过Provider.get()
对provision
执行任意次数的请求。Lazy
只会请求一个单独的provision
,但会延迟到第一次调用Lazy.get
的时候。下面的provision
方法请求的都是相同类型的provision
,但是每个都暗含不同的语义:
SomeType getSomeType();
Provider<SomeType> getSomeTypeProvider();
Lazy<SomeType> getLazySomeType();
1.2 Members-injection methods(成员注入型方法)
Members-injection
方法有一个单独的参数,它将依赖注入到参数实例的每一个@Inject
成员变量和方法中。成员注入型方法的返回值可能是void或者返回它的唯一参数以方便链式调用。下面是有效的成员注入型方法的声明:
void injectSomeType(SomeType someType);
SomeType injectAndReturnSomeType(SomeType someType);
一个无参的返回MembersInjector
方法等价于一个成员注入方法。在返回的对象上调用MemberInjector.injectMembers
与一个成员注入方法的效果是一样的,例如:
MembersInjector<SomeType> getSomeTypeMembersInjector();
1.3 A note about covariance(不知道咋翻译,“协方差相关的一个知识点”?)
虽然一个类型的members-injection
方法可以接收它的子类型实例,但是只有参数类型及其超类型的@Inject
成员变量可以注入。其子类型的成员变量则不行。例如,给出下方的这些类型,当Child
实例传入到member-injection
方法injectSelf(Self instance)
中时,只有a
和b
可以注入到孩子的实例中。
class Parent {
@Inject A a;
}
class Self extends Parent {
@Inject B b;
}
class Child extends Self {
@Inject C c;
}
2. Instantiation(实例化)
Component
的实现例主要是通过生成的(generated) builder
实例化的。builder
的实例由component
的builder()
方法获得。如果component
中内嵌了一个@Component.Builder
类型,builder()
方法会返回一个生成的该类型实现例。如果不存在内嵌的@Component.Builder
, 返回的builder
会设置每一个使用module
和依赖类型的驼峰名命名的modules
和component
依赖。每个没有可见的默认构造方法的component
依赖和module
必须显式设置,但是任何带有默认或无参构造方法并对于component
实例可访问的component
依赖和module
可以省略。下面这是一个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();
}
在这个例子中,component
没有component
依赖且只有无参modules
,生成的component
也会有一个工厂方法create()
. SomeComponent.create()
和SomeComponent.builder().build()
都是有效和等价的。
3. Scope(作用域)
每个Dagger Component
使用scope
注解标注可以关联一个scope
. component
的实现确保对于scoped binding
,一个component
实例当中只有一个provision
. 如果component
声明了一个scope
, 在整个图的任何地方,它都只会包含unscoped bindings
或者该scope
的bindings
,例如
@Singleton @Component
interface MyApplicationComponent {
// this component can only inject types using unscoped or @Singleton bindings
}
为了获得与scope
注解相关的合适行为,调用者负责在合适的时候创建Component
实例。例如一个单例的component
在应用中只能实例化一次,而一个RequestedScoped
的component
每次请求时都要实例化。因为component
是自包含的实现,存在一个scope
就像将所有引用丢给component
实例一样简单。
4. Component relationships(组件的关系)
虽然使用单纯的unscoped bindings
的单独的component
有很多用处,许多应用还是有多scopes
的多component
交互的需求。Dagger提供(下面)两种机制关联Components.
4.1 Subcomponents(子组件)
关联两个components
最简单的方式是声明一个Subcomponent
. subcomponent
行为完全就像一个component
, 但是是在上一级(parent)component
或subcomponent
内部生成它的实现。这样的关系允许subcomponent
在被声明时 其实现继承它的parent
的所有binding
图。因为这个原因,一个subcomponent
在它关联到parent
之前是不完整的。
通过将subcomponent
类列入parentcomponent
的一个module
的subcomponents()
属性中声明subcomponent
.如此在parent component
内部绑定了Subcomponent.Builder
subcomponents
也可以通过parent component
或subcomponent
上的工厂方法声明。这样的方法名字任意,但是必须返回该subcomponent
.工厂方法的参数可以是该subcomponent
任意数量的modules
, 但至少必须包含缺少可见无参构造器的module
.下面是一个工厂方法的示例,该方法从一个singleton-scoped
parent创建一个request-scoped subcomponent
:
@Singleton
@Component
interface ApplicationComponent {
// component methods...
RequestComponent newRequestComponent(RequestModule requestModule);
}
4.2 Component dependencies(组件依赖)
虽然subcomponents
是组成bindings
子图最简单的方法,但是subcomponents
与parent
结合非常紧密;他们可以使用任意由他们的祖级(ancestor)component
和subcomponents
定义的binding.作为可选项,通过声明component
依赖,components
只能使用来自其他的component
接口的bindings
。当一个类型用作component
依赖,该依赖上面的每一个provision
方法被绑定为一个provider
.注意通过component
依赖,只有暴露为provision
方法的bindings
是有效的。