在Dagger2工作流程分析中,我们认识了@Module, @Component, @Provides, @Inject, @Named等注解。现在我们一起深入下Dagger2是如何生成一系列代码。
准备
推荐文章。
在Java领域内,很多前辈很早已经在做依赖注入的研究与实现,在前辈探索过总结出一些标准,Dagger2作为后来者,必定会跟随前辈的步伐。JSR-330是前辈们总结面向依赖注入使用者的规范,大家需要去了解下。
源码
google在实现Dagger2时,依赖了部分已经比较稳定和完善google的开源库。所以我们需要准备一下源码。
Dagger2依赖auto
库中的common
,auto-value
和auto-service
;
javapoet是square团队的杰作,使用javapoet可以方便的通过注解生成java源码;
初步看看
clone Dagger2的源码后,我们会看到以下目录结构:
目前我们只需要关注core
和compiler
中的主要代码。
在core
中定义了支持的自定义注解如下图(除去MembersInjector.java,package-info.java)。
以上这些注解的作用以及使用方法在文档中都有,在这里不赘述。
compiler
是本次分析的重点,这里完成注解的具体处理策略。
核心源码分析
大家知道Dagger2时在编译时通过分析注解完成依赖注入工作,首先我们来定位下处理注解入口。
我们可以从Dagger2使用google自家的auto-common
,auto-service
和auto-value
下手。
打开auto源码去看看。
我们把焦点放在common
中的BasicAnnotationProcessor.java和service
中的AutoService.java上。
BasicAnnotationProcessor的核心代码分析:
- 内部接口ProcessingStep,其中annotations方法用于指定ProcessingStep支持处理的注解,process方法用于确定每个注解的处理方式;
- BasicAnnotationProcessor.java是一个抽象类,抽象方法initSteps,用于指定具体的注解处理步骤;
- BasicAnnotationProcessor继承自AbstractProcessor,实现
public final ImmutableSet<String> getSupportedAnnotationTypes()
和public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
方法,确定BasicAnnotationProcessor是对注解处理的具体实现的父类; private void process(ImmutableSetMultimap<Class<? extends Annotation>, Element> validElements)
是最核心的方法,其中循环ProcessingSteps,依次处理每个step的annotations和process,详细见源码。
ComponentProcessor的核心代码分析:
ComponentProcessor继承自BasicAnnotationProcessor,实现initSteps和postProcess方法。除此之外,还使用AutoService注解修饰。
其中initSteps中返回内容如下:
初步结论:
Dagger2把所有注解的处理拆分成上图这些步骤,按照步骤依次执行,生成相关的java代码。其中每个ProcessingStep的任务相关独立。