4.Dagger2.38.1源码解析-ComponentProcessor注解生成对象

123 阅读11分钟

简介

使用不同注解的节点生成不同对象,对该对象的核心属性介绍,以及一些核心方法说明。

在学习的过程中最好拿一个笔对存在的问题进行记录,后面可能会找到,而且要学会不断翻阅前面的内容。如果都找不到需要的答案,我相信这个就是自身找到的亮点问题,对自身提升也有很大帮助。

节点生成的对象

ComponentDescriptor

该对象的生成在ComponentProcessingStep中继校验之后调用如下方法完成ComponentDescriptor对象的生成:

生成的是componentDescriptor对象:

 //重头戏,生成ComponentDescriptor对象
    ComponentDescriptor componentDescriptor =
            componentDescriptorFactory.rootComponentDescriptor(component);

生成subcomponentDescriptor对象:

    ComponentDescriptor subcomponentDescriptor =
            componentDescriptorFactory.subcomponentDescriptor(subcomponent);

component节点生成当前对象,属性如下:

  1. ComponentAnnotation annotation:当前component节点使用的注解信息,自行查看ComponentAnnotation对象;

  2. TypeElement typeElement:表示component节点(或module节点);

  3. ImmutableSet dependencies:componentAnnotation#dependencies里面dependency节点生成DEPENDENCY类型的ComponentRequirement对象集合,自行查看《多种类型查询总结》ComponentRequirement对象

  4. ImmutableSet modules:componentAnnotation#modules的module节点,以及该module节点上moduleAnnotation#includes的module节点,自行查看ModuleDescriptor对象

  5. ImmutableMap<ExecutableElement, ComponentRequirement> dependenciesByDependencyMethod:收集componentAnnotation#dependencies中dependency节点 ①无参②返回类型不是void 方法。K:dependency无参返回类型不是void方法,V:当前方法所在dependency节点生成的ComponentRequirement对象;

  6. ImmutableSet scopes:

  • (1)component节点使用Scope注解修饰的注解集合;

  • (2)如果componentAnnotation是production类型(@ProductionComponent,@ProductionSubcomponent或@ProducerModule),还会添加@ProductionScope注解;

  1. ImmutableSet childComponentsDeclaredByModules:(当前component节点上componentAnnotation#modules以及moduleAnnotation#includes里面的所有module节点,如果是module节点直接使用当前module节点的)moduleAnnotation#subcomponents里面的subcomponent节点集合生成ComponentDescriptor对象;

  2. ImmutableBiMap<ComponentDescriptor.ComponentMethodDescriptor, ComponentDescriptor> childComponentsDeclaredByFactoryMethods:当前component节点上返回类型是subcomponent节点的方法。K:返回类型是subcomponent节点的componentMethod方法生成的ComponentMethodDescriptor对象,V:当前方法返回类型subcomponent节点生成的ComponentDescriptor对象;

  3. ImmutableBiMap<ComponentDescriptor.ComponentMethodDescriptor, ComponentDescriptor> childComponentsDeclaredByBuilderEntryPoints:返回类型是subcomponent.creator节点(Builder)的componentMethod方法。K:返回类型是subcomponent.creator节点的componentMethod方法生成该方法生成的ComponentMethodDescriptor对象,V:componentMethod方法的返回类型subcomponent节点生成的ComponentDescriptor对象;

  4. ImmutableSet<ComponentDescriptor.ComponentMethodDescriptor> componentMethods:表示componentMethod的方法生成的ComponentMethodDescriptor集合,ComponentMethodDescriptor自行查看

  5. Optional creatorDescriptor:component.creator节点如果存在,那么生成一个ComponentCreatorDescriptor,自行查看《多种类型查询总结》ComponentCreatorDescriptor对象

ComponentAnnotation对象

表示component节点使用的componentAnnotation注解生成的对象(当然了,也可能当前component节点其实是一个module节点,这部分逻辑也是一个瑕疵,为啥module节点可以作为一个伪component节点!!!)

ComponentAnnotation有两个子类:一个是RealComponentAnnotation表示这是真的componentAnnotationAll;一个是FictionalComponentAnnotation表示moduleAnnotation,属性如下

  1. AnnotationMirror annotation:表示使用的注解;

  2. boolean isSubcomponent:当前使用的注解是ProductionSubcomponent或Subcomponent;

  3. boolean isProduction:当前使用的注解是ProductionComponent或ProcutionSubcomponent或ProducerModule;

  4. boolean isRealComponent:是否是componentAnnotation注解,使用的如果是moduleAnnotation该属性肯定是false;

  5. ImmutableSet modules:如果是isRealComponent表示componentAnnotation#modules的module节点;否则表示moduleAnnotation#includes里面的module节点集;

  6. ImmutableList dependencies:componentAnnotation#dependencies里面的节点。

ComponentMethodDescriptor对象

component节点上非private、非static、abstract(接口除外)的方法,属性如下:

  1. ExecutableElement methodElement:componentMethod方法节点;

  2. Optional dependencyRequest:根据参数个数生成依赖,最多只有一个参数,请去自行查看《多种类型查询总结》文章的DependencyRequest

  • 注:如果componentMethod返回类型是subcomponent为什么没有当前dependencyRequest依赖字段???答:如果是componentMethod返回类型是subcomponent,那么当前方法参数必须是module节点表示(该module节点存在于subcomponentAnnotation#modules及其子module的moduleAnnotation#includes),这里的module节点参数表示module实例化对象;
  1. Optional subcomponent:返回类型是subcomponent或者是subcomponent.creator,那么针对该subcomponent生成ComponentDescriptor对象:
  • (1)当前componentMethod方法没有使用Qualifier修饰的注解修饰情况下才会根据subcomponent节点生成该componentDescriptor对象;

  • (2)如果方法返回类型只是subcomponent节点,那么当前对象不会有dependencyRequest属性;

ComponentCreatorDescriptor

creator节点生成的对象,属性如下:

  1. ComponentCreatorAnnotation annotation:creatorAnnotation注解;

  2. TypeElement typeElement:creator节点;

  3. ExecutableElement factoryMethod:

  • (1)表示Factory(工厂模式)类型的creator节点,如果是工厂模式,那么当前creator节点有且仅有给factoryMethod方法;该模式下方法参数不受限制;

  • (2)表示Builder(构建者模式)类型的creator节点,方法无参,并且还有无数setterMethod每次传递一个参数;

  • (3) (1)和(2)的共同特点是返回类型都是creator节点所在component父节点或其子类节点;

  • 注:这里感觉如果是Builder模式使用buildMethod是否更好一点,因为后面用起来很多时候会出现思维混乱的情况。

  1. ImmutableSetMultimap<ComponentRequirement, ExecutableElement> unvalidatedSetterMethods:
  • (1)表示Builder(构建者模式)类型类型的setterMethod方法,该方法有且仅有一个参数;

  • (2)对参数和参数类型生成ComponentRequirement对象,自行查看《多种类型查询总结》ComponentRequirement

  • (3) Map<K = 参数、参数类型和方法生成的ComponentRequirement对象,V = 当前方法节点>;

  1. ImmutableSetMultimap<ComponentRequirement, VariableElement> unvalidatedFactoryParameters:factoryMethod(工厂模式)方法里面的参数、参数类型和方法生成的ComponentRequirement对象,Map<K = 参数、参数类型和方法生成的ComponentRequirement对象,V = 当前参数节点>,参考《多种类型查询总结》ComponentRequirement对象

ModuleDescriptor

module节点生成的对象,属性如下:

  1. TypeElement moduleElement:module节点;

  2. ImmutableSet includedModules:当前module及其父级module节点深入遍历,①moduleAnnotation#includes;②如果使用了ContributesAndroidInjector的方法,那么将 其所在父节点 + "_" + 该方法首字母大写 拼接的名称作为一个module节点加入;

  3. ImmutableSet bindings:module节点上的绑定,当前module节点(或module中的Kotlin Companion Object对象)中使用 @Provides(生成ProvisionBindings对象)或@Produces(生成ProductionBinding对象)修饰的bindingMethod绑定,自行查阅绑定声明;

  4. ImmutableSet multibindingDeclarations:使用了@Multibinds的bindingMethod方法生成的对象,自行查看MultibindingDeclaration;

  5. ImmutableSet subcomponentDeclarations:moduleAnnotation#subcomponent里面的subcomponent节点生成的对象,自行查看SubcomponentDesclaration

  6. ImmutableSet delegateDeclarations:使用@Binds修饰的bindingMethod方法,自行往下查看DelegateDeclaration

  7. ImmutableSet optionalDeclarations:使用@BindsOptionalOf修饰的bindingMethod方法,自行往下查看OptionalBindingDeclaration

  8. ModuleKind kind:moduleAnnotation注解类型,MODULE和PRODUCER_MODULE分别表示Module注解和ProducerModule注解。

绑定声明

bindingMethod( @Provides、@Produces、@Binds、@BindsOptionalOf、@Multibinds)方法生成的对象 外加 moduleAnnotation#subcomponent里面的subcomponent节点生成的对象

ProvisionBinding

@Provides修饰的bindingMethod方法生成ProvisionBinding对象

属性如下:

  1. BindingKind kind:PROVISION类型,请查看《多种类型查询总结》BindingKind绑定类型;

  2. Optional scope:当前绑定使用的Scope注解修饰的注解;

  3. Optional nullableType:使用了Nullable注解;

  4. ContributionType contributionType,以下四种状态:

  • ContributionType.Map:表示使用了IntoMap修饰;

  • ContributionType.SET:表示使用了IntoSet修饰;

  • ContributionType.SET_VALUES:表示使用了ElementsIntoSet修饰;

  • ContributionType.UNIQUE:表示没有使用以上三种类型;

  1. Element bindingElement:当前bindingMethod方法节点;

  2. TypeElement contributingModule:当前bindingMethod所在的module节点;

  3. boolean isModuleKotlinObject: module节点是否Kotlin Object对象或Kotlin Companion Object对象;

  4. Key key:使用@Provides修饰的bindingMethod方法生成Key,key包括属性

  • (1)qualifier:方法上使用的Qualifier修饰的注解修饰;

  • (2)如果该方法使用了@IntoSet或@IntoMap或@ElementsIntoSet,则key对象需要添加MultibindingContributionIdentifier identifier属性;

  • (3)type属性,type来源如下

  • ①如果@Provides修饰的bindingMethod使用了@IntoSet修饰,那么type = Set<bindingMethod返回类型>;

  • ②如果使用了@ElementsIntoSet修饰,那么检查返回类型是Set类型即可,type = bindingMethod返回类型

  • ③如果使用了@IntoMap修饰(同时一定会使用到MapKey注解修饰的注解修饰,该注解的方法为Map<K,V>提供K),type = Map<K = MapKey修饰的注解的方法值,V = Provider<方法返回类型>>

  • ④其他type = 方法返回类型;

  1. Iterable dependencies:方法参数和方法参数类型生成依赖,请自行查看《多种类型查询总结》DependencyRequest对象

  2. Optional<Equivalence.Wrapper> wrappedMapKeyAnnotation:使用了MapKey修饰的注解修饰情况;

  3. ContributionBinding unresolved: 如果方法和方法类型不一致(例如一个是List,一个是List),那么还需要对当前方法和方法所在类生成未解析绑定。

ProductionBinding

@Produces修饰的bindingMethod方法生成ProductionBinding对象。

属性如下:

  1. BindingKind kind:PRODUCTION类型,请查看BindingKind绑定类型

  2. ProductionKind productionKind:表示当前方法返回类型:

  • (1)FUTURE:当前方法返回类型是ListenableFuture< T>

  • (2)SET_OF_FUTURE:当前方法使用了@ElementsIntoSet修饰 && 返回类型是Set<ListenableFuture< T>>;

  • (3)IMMEDIATE: 除了(1)和(2)以外的其他类型;

  1. Iterable<? extends TypeMirror> thrownTypes:方法throws异常(@Produces修饰的方法允许继承Exception或Error及其子类型的异常);

  2. DependencyRequest executorRequest,生成一个依赖:

  • (1)该依赖的key对象:①ProductionImplementation作为qualifier;②Executor作为type;

  • (2)RequestKind:PROVIDER;

  1. DependencyRequest monitorRequest,生成一个依赖:
  • (1)该依赖的key对象:ProductionComponentMonitorr作为type;

  • (2)RequestKind:PROVIDER;

  1. ContributionType contributionType,以下四种状态:
  • ContributionType.Map:表示使用了IntoMap修饰;

  • ContributionType.SET:表示使用了IntoSet修饰;

  • ContributionType.SET_VALUES:表示使用了ElementsIntoSet修饰;

  • ContributionType.UNIQUE:表示没有使用以上三种类型;

  1. Element bindingElement:当前bindingMethod方法节点;

  2. TypeElement contributingModule:当前bindingMethod方法所在的module节点;

  3. boolean isModuleKotlinObject: module节点是否Kotlin Object或Kotlin Companion Object对象;

  4. Key key:方法返回类型生成Key,key包括属性

  • (1)qualifier:bindingMethod方法上使用的Qualifier修饰的注解修饰;

  • (2)identifier:如果该方法使用了@IntoSet或@IntoMap或@ElementsIntoSet,则key对象需要添加MultibindingContributionIdentifier identifier属性;

  • (3)type:如果bindingMethod方法返回类型是ListenableFuture< T> 或 FluentFuture< T>,下面是对T作为返回类型处理;如果bindingMethod方法使用了@ElementsIntoSet并且方法返回类型是Set<ListenableFuture< T> 或 FluentFuture< T>>,下面是对set< T>作为返回类型处理;

  • ①如果bindingMethod使用了@IntoSet修饰,那么type = Set< T>;

  • ② 如果使用了@ElementsIntoSet修饰,那么检查返回类型是Set< T>类型即可,type = T类型

  • ③ 如果使用了@IntoMap修饰(同时一定会使用到MapKey注解修饰的注解修饰,该注解的方法为Map<K,V>提供K),type = Map<K = MapKey修饰的注解的方法值,V = Producer>

  • ④ 其他type = 方法返回类型;

  1. Iterable dependencies:方法参数和方法参数类型生成依赖,请自行查看《多种类型查询总结》DependencyRequest对象

  2. Optional<Equivalence.Wrapper> wrappedMapKeyAnnotation:使用了MapKey修饰的注解修饰情况;

  3. ContributionBinding unresolved: 如果方法和方法类型不一致(例如一个是List,一个是List),那么还需要对当前方法和方法所在类生成未解析绑定;

MultibindingDeclaration

@Multibinds修饰的方法是抽象方法或接口方法,并且无参。

module节点上使用@Multibinds注解修饰的bindingMethod方法生成该对象,核心属性

  1. Optional bindingElement:当前bindingMethod方法节点;

  2. Optional contributingModule:当前bindingMethod方法所在父级的module节点;

  3. Key key:方法和方法类型生成key对象,属性如下:

  • (1)Optional qualifier:当前bindingMethod方法使用的Qualifier注解修饰的注解修饰情况;

  • (2)type:如果returnType不是Map类型,直接使用bindingMethod方法的返回类型returnType;如果returnType是Map<K,V>类型,使用Map<K,Provider>类型(将V外包装一层Provider);

  1. ContributionType contributionType:根据returnType返回类型,判断ContributionType:
  • (1)如果bindingMethod方法的返回类型是Map<K,V>,contributionType = ContributionType.MAP;

  • (2)如果bindingMethod方法的返回类型是Set,contributionType = ContributionType.SET;

  • (3)除此之外没有其他情况,并且returnType不能是Map或Set不带泛型类型。

SubcomponentDeclaration

moduleAnnotation#subcomponents中的节点生成该对象,属性有:

  1. Optional bindingElement:表示moduleAnnotation#subcomponents方法节点;

  2. Optional contributingModule:当前moduleAnnotation修饰的module节点;

  3. Key key:针对subcomponent.creator节点生成的key对象,将当前subcomponent.creator节点类型作为type;

  4. TypeElement subcomponentType:subcomponent节点;

  5. ModuleAnnotation moduleAnnotation:moduleAnnotation注解信息。

DelegateDeclaration

@Binds注解修饰的bindingMethod方法是抽象方法或接口方法,方法有且仅有一个参数

module节点使用@Binds注解修饰的bindingMethod方法,属性有:

  1. ContributionType contributionType:当前使用@Binds注解的bindingMethod方法使用@IntoMap(表示ContributionType.MAP)、@IntoSet(ContributionType.SET)、@ElementsIntoSet(表示ContributionType.SET_VALUES)、或者都没有使用(ContributionType.UNIQUE);

  2. Key key:

  • (1)qulifier:bindingMethod方法上使用Qualifier注解修饰的注解;

  • (2)type:根据contributionType和returnType判断:

  • ①如果contributionType = ContributionType.UNIQUE,type = returnType;如果contributionType = ContributionType.SET_VALUES,判断返回类型是否是Set,type = returnType;

  • ②如果contributionType = ContributionType.SET,type = Set;

  • ③如果contributionType = ContributionType.MAP,type = Map<K = MapKey修饰的注解里面唯一的方法的值,V = returnType>;

  • (3)MultibindingContributionIdentifier identifier:如果contributionType != ContributionType.UNIQUE,那么该属性表示多重绑定类型;

  1. Optional bindingElement:当前绑定的bindingMethod方法节点;

  2. Optional contributingModule:当前方法所在module节点;

  3. DependencyRequest delegateRequest:当前方法存在有且仅有一个参数,该参数节点和参数类型生成参数依赖,自行查看DependencyRequest

  4. Optional<Equivalence.Wrapper> wrappedMapKey:当前绑定方法使用的MapKey注解修饰的注解。

OptionalBindingDeclaration

module节点使用@BindsOptionalOf修饰的bindingMethod方法,属性如:

  1. Optional bindingElement:当前bindingMethod方法;

  2. Optional contributingModule:当前绑定方法所在的module节点;

  3. Key key:

  • (1)qualifier:方法上使用@Qulifier修饰的注解;

  • (2)type:就是方法返回类型returnType,之所以type是返回类型returnType,因为@BindsOptionalOf修饰的方法不允许使用@IntoSet、@IntoMap、@ElementsIntoSet修饰。

总结

component节点以及其关联的module节点,componentMethod节点,creator节点,bindingMethod节点生成的对象已完成,但是感觉少了点什么,这里以一个关联图形来进一步说明,更加直观反映他们之间的关系。

图形制作文件

打开www.iodraw.com/diagram/工具直接将上面制作文件拖进去即可查看

图片花的不咋样,但是花了我好长时间!!!后面只需要对当前图片进行加工,当前图片也是后面工作的一个非常非常重要的参考。