简介
compile 'com.google.dagger:dagger:2.11'//2017-9-17最新版本为【2.11】
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'//dagger-compiler为编译时期生成代码等相关的类库
Dagger2 是一个Android依赖注入框架,由谷歌开发,最先的版本Dagger1 由Square公司开发。
依赖注入框架主要用于模块间解耦,提升代码的健壮性和可维护性。
Dagger 这个库的取名不只仅来自它的本意“匕首”,同时也暗示了它的原理。Jake Wharton 在对 Dagger 的介绍中指出,Dagger 即 DAG-er,这里的 DAG 即数据结构中的 DAG:有向无环图(Directed Acyclic Graph)。也就是说,Dagger 是一个基于有向无环图结构的依赖注入库,所以Dagger的使用过程当中不能出现循环依赖。
Android开发从一开始的MVC框架,到MVP,到MVVM,不断变化。如今MVVM的
data-binding还在实验阶段,传统的MVC框架Activity内部可能包含大量的代码,难以维护,如今主流的架构仍是使用MVP的方式。可是 MVP 框架也有可能
在Presenter中集中大量的代码,引入DI框架Dagger2 能够实现
Presenter 与 Activity 以及 Presenter 和其它业务逻辑之间的解耦,提升模块化和可维护性。
依赖注入就是将调用者须要的另外一个对象实例不在调用者内部实现,而是经过必定的方式从外部传入实例,解决了各个类之间的耦合。
那么这个外部,到底指的是哪里,若是指的是另外一个类,那么,另外一个类内部不就耦合了?能不能有一种方式,
将这些构造的对象放到一个容器中,具体须要哪一个实例时,就从这个容器中取就好了
。这样,
类的实例和使用就不在有联系了,而是经过一个容器将他们联系起来
,实现了解耦。这个容器,即是Dagger2。
Dagger2的原理是:
在【编译期】生成相应的依赖注入代码
。这也是和其余依赖注入框架不一样的地方,
其余框架是在【运行时】经过【反射】获取【注解内容】
,影响了运行效率。
【Dagger1】
Dagger1能够说是现在Android上最流行的依赖注入框架。它是由Square公司受到Guice启发建立的。
基本特色:
- 多个注入点:依赖,经过injected
- 多种绑定方法:依赖,经过provided
- 多个modules:实现某种功能的绑定集合
- 多个对象图: 实现一个范围的modules集合
Dagger1是在编译的时候实行绑定,不过也用到了反射机制。但这个反射不是用来实例化对象的,而是用于图的构成。Dagger会在运行的时候去检测是否一切都正常工做,因此使用的时候会付出一些代价:偶尔会无效和调试困难。
【Dagger2】
Dagger2是Dagger1的分支,由谷歌公司接手开发。Dagger2是受到AutoValue项目的启发。刚开始,Dagger2解决问题的基本思想是:利用生成和写的代码混合达到看似全部的产生和提供依赖的代码都是手写的样子。
若是咱们将Dagger2和1比较,他们两个在不少方面都很是类似,但也有很重要的区别,以下:
- 再也没有使用反射:图的验证、配置和预先设置都在编译的时候执行。
- 容易调试和可跟踪:彻底具体地调用提供和建立的堆栈
- 更好的性能:谷歌声称他们提升了13%的处理性能
- 代码混淆:使用派遣方法,就如同本身写的代码同样
固然全部这些很棒的特色都须要付出一个代价,那就是缺少灵活性,例如:Dagger2没用反射因此没有动态机制。
【JSR-330】
为了最大程度的提升代码的复用性、测试性和维护性,java的依赖注入为注入类中的使用定义了一整套注解(和接口)标准。Dagger1和Dagger2(还有Guice)都是基于这套标准,给程序带来了稳定性和标准的依赖注入方法。
使用dagger2的好处
好处:
- 增长开发效率、省去重复的简单体力劳动
首先new一个实例的过程是一个重复的简单体力劳动,dagger2彻底能够把new一个实例的工做作了,所以咱们把主要精力集中在关键业务上、同时也能增长开发效率上。
省去写单例的方法,而且也不须要担忧本身写的单例方法是否线程安全,本身写的单例是懒汉模式仍是饿汉模式,由于dagger2均可以把这些工做作了。
- 更好的管理类实例
每一个app中的ApplicationComponent管理整个app的全局类实例,全部的全局类实例都统一交给ApplicationComponent管理,而且它们的生命周期与app的生命周期同样。
每一个页面对应本身的Component,页面Component管理着本身页面所依赖的全部类实例。
由于Component,Module,整个app的类实例结构变的很清晰。
- 解耦
假如不用dagger2的话,一个类的new代码是很是可能充斥在app的多个类中的,假如该类的构造函数发生变化,那这些涉及到的类都得进行修改。设计模式中提倡把容易变化的部分封装起来。
解耦还有个好处,就是方便测试,若须要替换为网络测试类,只须要修改相应的Module便可。
咱们用了dagger2后。
- 假如是经过用Inject注解标注的构造函数建立类实例,则即便构造函数变的天花乱坠,咱们基本上都不须要修改任何代码。
- 假如是经过工厂模式Module建立类实例,Module其实就是把new类实例的代码封装起来,这样即便类的构造函数发生变化,只须要修改Module便可。
GitHub中的介绍
A fast
dependency injector for Android and Java.
适用于Android和Java的快速依赖注入器。
【About Google's Fork】
Dagger 2 is a compile-time evolution approach to dependency injection. Taking the approach started in Dagger 1.x to its ultimate conclusion, Dagger 2.x eliminates all reflection, and improves code clarity by removing the traditional ObjectGraph/Injector in favor of user-specified @Component interfaces.
Dagger 2是
接近依赖注入的一种编译时进化。采用Dagger 1.x开始的方式达成
最终结论,Dagger 2.x
消除了全部的反射,并经过删除传统的ObjectGraph / Injector来改善代码
清晰度,并以用户指定的@Component接口来取代。
evolution [ˌɛvəˈluʃən, ˌivə-] n. 演变; 进化; 发展;
approach [əˈproʊtʃ] vt.接近,走近,靠近; vt.接近; 着手处理; 使移近; n. 方法; 途径; 接近;
in favor of 同意[支持](某人或某事物); 以…取代; (支票) 以某人[某部门]为受款人;
This github project represents the Dagger 2 development stream. The earlier project page (Square, Inc's repository) represents the earlier 1.0 development stream. Both versions have benefitted from strong involvement from Square, Google, and other contributors.
这个github项目表明了Dagger 2开发流。较早的项目页面(Square,Inc的存储库)表明较早的1.0开发流。这两个版本都
受益于Square、Google和其余贡献者的强烈
参与。
Dagger is currently in active development, primarily internally at Google, with regular pushes to the open-source community. Snapshot releases are auto-deployed to sonatype's central maven repository on every clean build with the version HEAD-SNAPSHOT.
Dagger 目前正在积极发展,主要是内部在谷歌,按期push到开源社区。快照版本将自动部署到sonatype的中央maven存储库,每一个干净的版本与版本HEAD-SNAPSHOT。
【Documentation】
您能够在这里找到
扩展使用说明和其余有用信息的匕首文档。能够在API文档中找到
实质的使用信息。
您还能够从原始
提案中了解更多信息,Greg Kick的此演讲以及**邮件列表。
【Installation】
You will need to include the dagger-2.x.jar in your application's runtime. In order to activate code generation and generate implementations to manage your graph you will need to include dagger-compiler-2.x.jar in your build at compile time.
您可能须要将dagger-2.x.jar包含在应用程序的运行时中。为了激活代码生成器并生成实现以管理图形,您将须要在编译时将dagger-compiler-2.x.jar包含在构建中。
Gradle配置
一、在项目的build.gradle中添加:
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'//每一个Android项目默认都会带的
//PS:在新版本中千万不要加这些,日了狗了,加上去以后反而不会生成DaggerXXXComponent。
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'//这个是须要咱们手动添加的,apt是用于自动生成代码来进行依赖注入的
}
android-apt是Gradle编译器的插件,根据其官方文档,主要两个目的:
- 编译时使用该工具,最终打包时不会将该插件打入到apk中。
- 可以根据设置的源路径,在编译时期生成相应代码。
二、在module的build.gradle中添加:
apply plugin: 'com.android.application'//每一个Android项目默认都会带的。在build.gradle的第一行
//PS:在新版本中千万不要加这些,日了狗了,加上去以后反而不会生成DaggerXXXComponent。
apply plugin: 'com.neenbedankt.android-apt'//apt支持
三、在module的build.gradle中添加:
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'//dagger-compiler为编译时期生成代码等相关的类库
在android-apt的文档中,也推荐使用这种方式。由于,编译时期生成代码的类库在运行期并不须要,那么将其分为两个库:运行类库
butterknife/
dagger和 编译器生成代码类库
butterknife-compiler/
dagger-compiler。那么在打包时,就不须要将
butterknife-compiler/
dagger-compiler打入其中,减少APK 的大小。
四、其余配置
If you're using classes in
dagger.android you'll also want to include:
compile 'com.google.dagger:dagger-android:2.x'
compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
If you're using the
Android Databinding library, you may want to increase the number of errors that
javac will print. When Dagger prints an error, databinding compilation will halt and sometimes print more than 100 errors, which is the default amount for javac. For more information, see
Issue 306.
若是您正在使用Android Databinding库,您可能须要增长javac将打印的错误数量。当Dagger打印错误时,数据绑定编译将中止,有时会打印超过100个错误,这是javac的默认值。 有关详细信息,请参阅问题306。
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xmaxerrs" << "500" // or whatever number you want
}
}
一个简单的Dagger2示例
经过Dagger2的目的是将程序分为三个部分:
- - 实例化部分:对象的实例化。相似于容器,将类的实例放在容器里。
- - 调用者:须要实例化对象的类。
- - 沟通桥梁:利用Dagger2中的一些API 将二者联系。
实例化部分Module:
@Module//做为实例对象的容器
public class MainModule {
String name;
public MainModule(String name) {
this.name = name;
}
@Provides//标注可以提供实例化对象的方法。方法名字能够随意,但建议以provider开头
Person providerPerson() {//先判断Module中是否有提供该对象实例化的方法(根据返回值类型及@Provides注解来判断),若是有则注入返回的对象
return new Person(name);//若是没有,则查找Inject注解的构造函数。若是有,则注入使用此构造方法建立的对象
//若是@Provides方法或@Inject构造方法须要参数,则先按一样的步骤初始化参数。若存在参数但没法初始化参数,则编译不经过。
}
}
沟通桥梁部分Component:
@Component(modules = MainModule.class) //做为桥梁,沟通调用者和依赖对象库
public interface MainComponent {
void inject(MainActivity activity);//定义注入的方法。方法名随意,但建议以inject开头
}
调用者Actvity:
public class MainActivity extends AppCompatActivity {
@Inject Person person;//标注须要注入的对象。注意:使用@Inject时,不能用private修饰成员属性
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DaggerMainComponent.builder().mainModule(new MainModule("白乾涛")).build().inject(this);
Log.i("bqt", person.name);//包青天。若是去掉providerPerson上的【@Provides】注解,则会调用Person具备@Inject的构造方法
}
}
看一下Person类:
public class Person {
public String name;
@Inject
public Person() {
name = "默认的名字";
}
public Person(String name) {
this.name = name;
}
}
总结:dagger2依赖注入的步骤
dagger2进行一次依赖注入的步骤:
根据@Inject注解,查找须要依赖注入的对象。注意:使用@Inject注解时,不能用private修饰成员属性或构造方法,不然编译不经过,提示以下错误:
Error:(16, 25) 错误: Dagger does not support injection into private fields
Error:(54, 10) 错误: Dagger does not support injection into private constructors
- 先判断Module中是否有提供该对象实例化的方法(即:根据返回值类型及是否@Provides注解来判断),若是有:
- 若不存在参数,则直接初始化该类实例,这次依赖注入到此结束!
- 若存在参数,则从**步骤1**开始依次初始化每一个参数(PS:若存在参数但没法初始化参数,则编译不经过)
- 若不存在建立类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
- 若不存在参数,则直接初始化该类实例,这次依赖注入到此结束!
- 若存在参数,则从**步骤1**开始依次初始化每一个参数(PS:若存在参数但没法初始化参数,则编译不经过)
- PS:若存在多个@Inject注解的构造函数,须要使用@Qulifier限定符,不然编译不经过,提示以下错误:
Error:(51, 9) 错误: Types may only contain one @Inject constructor.
> java.lang.IllegalStateException: Found multiple @Inject constructors: [Person(), Person(java.lang.String)]
若是以上两种方式都没有提供,则
编译不经过,提示以下错误:
Error:(44, 7) 错误: com.bqt.dagger.Person cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
其实这个步骤是一个递归的过程,而且在查找类的实例的过程当中Module的级别要高于Inject。
PS:原本经过@Inject就能够完成依赖注入了,为何还要用到Module类来提供依赖呢?
这是为了适配
第三方类库中的类(咱们没办法给修改这些类),或那些
没有
提供
构造方法的类(
好比单例模式的类、系统类、框架类,好比Activity,其构造方法通常都是私有的),咱们没法给这些类的构造方法添加@Inject标注,只能经过
Module类来提供依赖。
Component的组织方式
假如一个app中只有一个Component,那这个Component是很难维护、而且变化率是很高,很庞大的,就是由于Component的职责太多了致使的。因此就有必要把这个庞大的Component进行划分,划分为粒度小的Component。
划分的规则建议是这样的:
- 要有一个全局的Component,负责管理整个app的全局类实例,全局类实例是整个app都要用到的类的实例,这些类基本都是单例的
- 每一个【页面】对应一个Component,好比一个Activity页面定义一个Component,一个Fragment定义一个Component。固然这不是必须的,有些页面之间的依赖的类是同样的,能够公用一个Component。
为何以页面为粒度来划分Component?
- 一个app是由不少个页面组成的,从组成app的角度来看一个页面就是一个完整的最小粒度了。
- 一个页面的实现是要依赖各类类的,能够理解成一个页面把各类依赖的类组织起来共同实现一个大的功能,每一个页面都组织着本身的须要依赖的类,一个页面就是一堆类的组织者。
- 划分粒度不能过小了。假如使用mvp架构搭建app,划分粒度是基于每一个页面的m、v、p各自定义Component的,那Component的粒度就过小了,定义这么多的Component,管理、维护就很很是困难。
总体来讲,在Android项目中,以页面划分Component在管理、维护上面相对来讲更合理。
Scope的真正用处就在于Component的组织:
- 更好的管理Component之间的组织方式,无论是依赖方式仍是包含方式,都有必要用自定义的Scope注解标注这些Component,这些注解最好不要同样,不同是为了能更好的体现出Component之间的组织方式。还有编译器检查有依赖关系或包含关系的Component,若发现有Component没有用自定义Scope注解标注,则会报错。
- 更好的管理Component与Module之间的匹配关系,编译器会检查 Component管理的Modules,若发现标注Component的自定义Scope注解与Modules中的标注建立类实例方法的注解不同,就会报错。
- 可读性提升,如用Singleton标注全局类,这样让程序猿立马就能明白这类是全局单例类。
涉及到的注解介绍
单词释义
Dagger [ˈdæɡɚ] n. 匕首; 短剑; vt. 用剑刺;
Inject [ɪnˈdʒɛkt] vt.(给…)注射(药物等);(给…)注射(液体);(给…) 添加;(给…)投入(资金);
Component [kəmˈpoʊnənt] n. 成分; 组分; 零件; [数] 要素; adj. 成分的; 组成的; 合成的; 构成的;
Module [ˈmɑ:dʒul] n. 模块; 组件; (宇宙飞船上各个独立的) 舱; 测量流水等的单位;
Scope [skoʊp] n.(处理、研究事务的)范围; 眼界,见识; (活动或能力的)余地; 广袤,地域; v.审视,仔细研究;
Singleton [ˈsɪŋɡəltən] n.一个,独身,单独;
Qualifier [ˈkwɑ:lɪfaɪə(r)] n.合格者,已取得资格的人; [语] 修饰语; 预选赛,资格赛;
【Inject】
用来标注所依赖的目标类的实例和所依赖的目标类的构造函数。带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类。
Identifies injectable constructors, methods, and fields. May apply to static as well as instance members. An injectable member may have any access modifier (private, package-private, protected, public). Constructors are injected first, followed by fields, and then methods. Fields and methods in superclasses are injected before those in subclasses. Ordering of injection among fields and among methods in the same class is not specified.
标识可注入的构造函数,方法和字段。可能适用于静态和实例成员。可注射成员能够具备任何访问修饰符。首先注入构造函数,后跟字段,而后是方法。超类中的字段和方法被注入到子类以前。没有指定在同一类中的字段之间和方法之间的注入顺序。
Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class.
可注射构造函数用@Inject注释,并接受零个或多个依赖关系做为参数。 @Inject能够每一个类最多只能应用一个构造函数。
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})//方法,构造方法,字段
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Inject {
}
【Module】
带有此注解的类实际上是一个简单工厂模式,去做用就是建立对象。带有此注解的类的方法基本都是建立类实例的方法,这些方法须要用@Provides注解,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所须要的依赖。
//Annotates a class that contributes to the object graph.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//类
public @interface dagger.Module {
/**
* Additional额外的、补充的 @Module-annotated classes from which this module is composed 组成.
* The de-duplicated复制出的 contributions of the modules in includes,
* and of their inclusions recursively递归地, are all contributed to the object graph.
*/
Class<?>[] includes() default {};//表明此Module依赖其余Module,效果和在Component中直接依赖多个Module同样。
}
【Provides】
用来标注Module类中建立类实例的方法,这些方法就是所提供的依赖。
/**
* Annotates methods of a Module to create a provider method binding. The method's return type is bound to its returned value.
* The Component component implementation will pass dependencies to the method as parameters.
*/
@Documented
@Target({ElementType.METHOD})//方法
@Retention(RetentionPolicy.RUNTIME)
public @interface dagger.Provides {
Provides.Type type() default Provides.Type.UNIQUE;
public static enum Type {
UNIQUE, SET, SET_VALUES, MAP;
private Type() {
}
}
}
【Component】
带有此注解的类是将Inject和Module联系起来的桥梁。编译后经过调用自动生成的DaggerXXX类的API,即可以从Module中获取依赖,并将依赖注入到Inject中。经过
modules属性能够把
多个
Module加入
此
Component中。
- dependencies表明须要哪个Component提供依赖,扩展当前Component的支持的依赖。用起来有几个注意事项。
- module表明经过哪个Module提供依赖。
/**
* Annotates an interface or abstract class for which a fully-formed, dependency-injected
* implementation is to be generated from a set of modules.
* The generated class will have the name of the type annotated with @Component prepended with Dagger.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//类
@Documented
public @interface dagger.Component {
Class<?>[] modules() default {};//指定此Component经过哪些Module获取依赖
//A list of types that are to be used as <a href="#component-dependencies"> component dependencies </a>.
Class<?>[] dependencies() default {};//指定此Component依赖于哪些Component,扩展当前Component的支持的依赖
@Target({ElementType.TYPE})
@Documented
public @interface Builder {
}
}
【Qualifier】
限定符,用于区别不一样的
对象以及提供
相应的对象实例的方法。Qualifier是一个元注解,用于注解其余注解,被注解的元素和@Named的做用彻底同样。
//Identifies qualifier annotations. Anyone can define a new qualifier.
@Target(ElementType.ANNOTATION_TYPE)//元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Qualifier {
}
【Named】
限定符,用于区别不一样的对象以及提供相应的对象实例的方法。Named注解有一个String类型的属性,因此能够直接传递值,但只能传递字符串。
注意:若是在一个字段上添加了Named注解(或任何用Qualifier注解标注的注解),那么必须能在Module中找到相应的提供对象的方法,不然报错。
//String-based Qualifier.
@Qualifier//@Named注解就是被元注解@Qualifier注解的注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface javax.inject.Named {
String value() default "";//@Named能够直接传递值,但只能传递字符串
}
【Scope】
注解做用域。Scope是一个元注解,用于注解其余注解,被注解的元素和@Singleton的做用彻底同样。
用@Scope标注的注解的主要做用:
- 一、限定对象的做用范围。可使基于同一Component实例的Module中建立的对象具备单例效果。
好比咱们用Scope注解标注一个自定义的名为MyScope的注解,假如在一个ComponentB前面加了@Myscope注解,那么若是对ComponentB管理的某个Module中的某个【ObjectA provideObjectA 】方法也加上@Myscope注解,那么Dagger2会在第一次使用该方法建立ObjectA时将它缓存起来,下次再须要提供ObjectA时,就直接使用缓存的对象,而不会再次建立新的ObjectA。若是没有加@Myscope注解,则会每次都建立一个新的ObjectA对象。
- 二、组织Component
Identifies scope annotations. A scope annotation applies to a class containing an injectable constructor and governs how the injector reuses instances of the type. By default, if no scope annotation is present, the injector creates an instance (by injecting the type's constructor), uses the instance for one injection, and then forgets it. If a scope annotation is present, the injector may retain the instance for possible reuse in a later injection. If multiple threads can access a scoped instance, its implementation should be thread safe. The implementation of the scope itself is left up to the injector.
标识范围注释。 范围注释
适用于包含可注入构造函数的类,并
控制注射器如何
重用类型的实例。默认状况下,若是没有范围注释,则注入器将建立一个实例(经过注入类型的构造函数),
使用该实例进行一次注入,而后将其忽略。 若是存在范围注释,注射器能够
保留实例以便在稍后的注射中可能从新使用。 若是
多个线程能够访问做用域实例,其实现应该是线程安全的。 范围自己的实现
由注射器决定。
Annotating scope annotations with @Scope helps the injector detect the case where a programmer used the scope annotation on a class but forgot to configure the scope in the injector. A conservative injector would generate an error rather than not apply a scope.
使用@Scope注释范围注释有助于注入器
检测程序员在类上使用范围注释但忘记配置注入器中的范围
的状况。
保守的注射器会产生错误,而不是应用范围。
@Target(ElementType.ANNOTATION_TYPE)//元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Scope {}
【Singleton】
做用为:标记为单例模式(这里有坑)。
注意,Singleton注解只是用Scope注解标注的一个普通的注解,其自己没有单例功能。Singleton注解的做用和任何一个用Scope注解标注的注解的做用彻底同样。使用Singleton后之因此在某些状况下具备单例效果,更多的是其余方面的缘由,而不只仅是由于添加了Singleton注解的缘由。
注意:
- 若是只在@Provides标注的方法上添加@Singleton注解(或者任何用@Scope标注的注解),而没在相应的Component类上添加,则编译失败!
- 相反,若是只在Component类上添加,而再也不相应的Module中用@Provides标注的方法上添加,则没有任何效果!
//Identifies识别 a type that the injector only instantiates实例化 once. Not inherited.不可遗传
@Scope//Singleton注解是被元注解@Scope注解的注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface javax.inject.Singleton {}//若是在Module中使用了此注解,在Component上也要使用该注解,不然编译失败
【Subcomponent】
在须要父组件所有的提供对象,这时咱们能够用包含方式而不是用依赖方式
//A subcomponent子组件 that inherits继承 the bindings绑定 from a parent Component or Subcomponent.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)//元注解
@Documented
public @interface dagger.Subcomponent {
/**
* A list of classes annotated with Module whose bindings are used to generate the subcomponent implementation.
* Note that through the use of经过使用 【Module.includes】 the full set of modules used to implement the subcomponent
* may include more modules that just those listed here.
*/
Class<?>[] modules() default {};
@Target(TYPE)
@Documented
@interface Builder {}
}
2017-9-17