前言
Dagger2.38.1源码解析指南,相当于一个整体框架的梳理,这样可以避免浪费时间去摸索它的功能板块,给后来者或者再来者提供一个学习参考。当然了,如果对源码一点不了解的情况下,不一定能达到我所说的效果,但是按照我说这个大纲去对照源码解析我感觉也是非常有帮助的。
理想是丰满的,现实是骨感的!!!对我来了一句你写的什么玩意儿肯定也大有人在!!!
当前是基于Dagger2.38.1源码解析得出来的结论,相对来说感觉更加精准,存在不足欢迎讨论。
还有其他代码,这里主要针对核心的AndroidProcessor和ComponentProcessor描述。
Dagger2.38.1版本源码非常有意思的一点是自己使用了自身的注解,所以它本身也是也给Dagger demo样本,为什么这么做的原因个人理解是:开发人员编写代码过程中是否容易出现理解偏差,反正我看代码的时候经常要问问自己我是谁,我到底在干啥!!!
我现在就像问我是谁,我到底在干啥???
想了一会,好吧!我继续,你随意!!!
整体架构
处理的是AndroidProcessor和ComponentProcessor。AndroidProcessor处理android特定注解,ComponentProcessor处理当前Dagger核心注解;
AndroidProcessor
两个板块,一个用于校验MapKey注解修饰的注解;一个用于处理ContributesAndroidInjector注解:先校验+节点生成对象,校验通过后对节点生成代码。
AndroidMapKeyValidator
对AndroidInjectionKey和ClassKey修饰的方法校验。
ContributesAndroidInjectorGenerator
-
使用ContributesAndroidInjector修饰的注解的方法节点,先通过AndroidInjectorDescriptor.createIfValid方法生成AndroidInjectorDescriptor对象,生成过程中校验;
-
生成实现代码。
这里也并没有完,AndridProcessor中处理的注解还会按照ComponentProcesso的注解规则处理。
ComponentProcessor
这里涉及到自身的注解,我们不做讲解,后面会有专门针对注解进行全面讲解,讲解基于当前2.38.1版本源码,我们仅仅给一个学习源码大纲,可以基于当前大纲指南去一步步学习。
处理注解的核心是ProcessingStepsModule接口的processingSteps方法,当前方法中的Step参数表示针对不同类型注解的处理。
这里有一个思想:横向-各个不同Step类处理不同类型的注解,纵向-每个Setp又按照(1:节点生成对象;2.对象校验;3.component特殊处理成对象;4.对象生成实现代码)步骤处理。
MapKeyProcessingStep
AndroidProcessor处理的AndroidInjectionKey和ClassKey如果被项目使用了,那么在当前step下也会进行二次操作。
处理MapKey修饰的注解:
-
MapKeyValidator完成校验工作;
-
校验通过后,如果①
mapKey#unwrapValue = false
或者 ②mapKey#unwrapValue = true
&&MapKey注解修饰的注解里面唯一的方法返回类型还是一个注解
,需要生成相关代码;
InjectProcessingStep 和 InjectBindingRegistry
InjectProcessingStep类
处理Inject修饰的普通方法、变量以及Inject或AssistedInject注解修饰的构造函数,正在的处理放在InjectBindingRegistryImpl类中。
该类主要通过调用InjectBindingRegistryImpl类的tryRegisterConstructor和tryRegisterMembersInjectedType方法;
- tryRegisterConstructor方法收集使用Inject或AssistedInject修饰的构造函数生成ProvisionBinding绑定对象;
- 仅此而已吗???no!!!如果存在Inject修饰的普通方法或变量还会调用tryRegisterMembersInjectedType方法收集;
- tryRegisterMembersInjectedType方法收集使用Inject修饰的普通方法或变量所在的父类生成的MembersInjectionBinding绑定对象;
- 当然也非仅此而已,深入遍历使用Inject修饰的变量(或普通方法)父类直到非Object,将其榨干 - 存在Inject修饰的变量(或普通方法)的父级类都生成MembersInjectionBinding绑定对象并收集。
这里就具体Dagger源码的魅力 - 细致,考虑全面。
InjectBindingRegistry类
这个接口的实现是InjectBindingRegistryImpl类,核心是其内部类BindingsCollection,主要通过该类收集ProvisionBinding绑定对象和MembersInjectionBinding绑定对象,并且在必要的时候对这些绑定对象生成对应的类(在ComponentProcessor调用injectBindingRegistry.generateSourcesForRequiredBindings
方法)
-
收集ProvisionBinding来源:Inject或AssistedInject修饰的构造函数;
-
收集MembersInjectionBinding绑定对象来源:
-
(1)Inject修饰的变量(或普通方法)所在父类(深入遍历其非Object对象,存在Inject修饰的变量或普通方法所在的父级类)生成MembersInjectionBinding绑定对象;
-
(2)对MembersInjector类型的type,在被匹配的情况下(匹配的意思就是相当于方法参数对应到参数类型),会生成MembersInjectionBinding绑定对象;
AssistedInjectProcessingStep
对AssistedInject修饰的构造函数以及该构造函数中的@Assited修饰的参数校验。内容简单。
AssistedFactoryProcessingStep
校验AssistedFactory修饰的类或接口。内容简单。
AssistedProcessingStep
校验Assisted修饰的参数。内容简单。
MonitoringModuleProcessingStep
ProductionComponent或ProductionSubcomponent修饰的类额外生成Module注解修饰的类,按照字面意思理解该生成类起到监控的作用。内容也不难。
MultibindingAnnotationsProcessingStep
校验IntoSet、IntoMap和ElementIntoSet三个注解。内容简单。
BindsInstanceProcessingStep
校验BindsInstance修饰的方法或参数,内容简单。
ModuleProcessingStep
处理Module和ProducerModule注解:
-
校验使用该注解的module节点;
-
校验通过后对module节点中的bindingMethod绑定方法生成代码:
-
(1)Provides修饰的bindingMethod方法使用FactoryGenerator和InaccessibleMapKeyProxyGnerator类生成;
-
(2)Procues修饰的bindingMethod方法使用ProducerFactoryGenerator和InaccessibleMapKeyProxyGnerator类生成;
-
(3)Binds修饰的BindingMethod使用InaccessibleMapKeyProxyGnerator类生成。
-
(4)以上三个最终都需要调用ModuleConstructorProxyGenerator类的generate方法;
也不是很难。
BindingMethodProcessingStep
收集Mdoule或ProducerModule修饰的module节点中的bindingMethod绑定方法:总共有5个,Providers、Produces、Binds、Multibinds和BindsOptionalOf修饰。
收集到的bindingMethod方法校验。
AnyBindingMethodValidator完成所有bindingMethod校验工作,在BindingMethodValidatorsModule接口的indexValidators方法用于收集并且归类这些bindingMethod方法:
-
ProvidesMethodValidator收集并校验Provides注解;
-
ProducesMethodValidator收集并校验Produces注解;
-
BindsMethodValidator收集并校验Binds注解;
-
MultibindsMethodValidator收集并校验Multibinds注解;
-
BindsOptionalOfMethodValidator收集并校验BindsOptionalOf注解;
如果刚开始看这个代码有点懵逼,如果看了我给的这个指南!!!嘿嘿嘿,保证让你精神饱满,充满活力,无任何副作用…咳咳咳,言归正传,继续!!!
ComponentProcessingStep
最难的理解的放在下面压轴讲解。
这块代码处理的是Component、ProductionComponent、Subcomponent、SubProductioncomponent注解,但是使用该注解的component节点还有一系列关联,我们以Component注解为例:
-
modules和dependencies分别关联module节点和dependency节点;
-
步骤1中的modules收集到的是使用Module和ProducerModule注解的module节点,module节点的主街上又关联includes(还是modle节点)和subcomponents(是subcomponent节点);
-
component节点中还有使用Component.Factory注解的creator节点;
-
module节点中还有使用Providers、Produces、Binds、Multibinds和BindsOptionalOf修饰的bindingMethod绑定方法;
-
creator节点中还有使用BindsInstance修饰的方法或方法参数;
除了关联,这里的纵向也是最深:
-
针对component节点及其关联生成ComponentDescriptor对象;
-
校验该对象;
-
全面校验生成的bindingGraph绑定图:
-
(1)Resolved解析绑定关系-核心中的核心;
-
(2)生成bindingGraph对象;
- 生成bindingGraph绑定图,并且对bindingGraph校验
- 3和4我们姑且理解为一个意思,详细看代码会发现略有不同;
- 对bindingGraph生成最终component代码,ComponentGenerator类实现,具体的实现放在componentImplementation类,执行generate方法,这里有一个核心,component的入口方法匹配:
-(1) component入口方法是什么?component节点中返回类型非subcomponent节点的方法。
-(2)通过ComponentRequestRepresentations类的getComponentMethod方法完成一系列匹配和代码生成工作,这里主要查看componentImplementation关系图;
- (3)多提几句,①如果看到源码再去理解,这里就当是故事看,别太较真;②入口方法匹配并且实现代码去看ComponentImplementation的addInterfaceMethods方法;
总结
可在QQ群:575306647 讨论