9.Dagger2.38.1源码解析-AndroidProcessor注解梳理

110 阅读5分钟

前言

前面主要针对component及其关联的subcomponent、module、bindingMethod、Inject等核心注解的解析。这里针对AndroidProcessor注解梳理以及ComponentProcessor中其他注解例如MapKey注解梳理

AndroidProcessor注解

AndroidMapKeyValidator类对AndroidInjectionKey和ClassKey注解的校验,这两个注解是使用MapKey注解修饰的注解;

ContributesAndroidInjectorGenerator类是针对ContributesAndroidInjector注解校验,以及代码生成。

AndroidMapKeyValidator

针对AndroidInjectionKey和ClassKey注解的校验。

AndroidInjectionKey注解只能修饰方法,ClassKey注解可以修饰方法和变量。

这里针对的是AndroidInjectionKey或ClassKey修饰方法校验,规则如下:

  1. 如果方法使用了AndroidInjectionKey或ClassKey修饰,那么当前方法不能使用Qualifier修饰的注解修饰;

  2. 方法返回类型如果不是AndroidInjector.Factory及其子类,不需要继续校验了,该方法直接被忽略;

  3. 如果该方法使用了Scope注解修饰的注解修饰,该方法必须使用@SuppressWarnings注解修饰,并且该@SuppressWarning注解包含dagger.android.ScopedInjectorFactory值;

  4. 方法返回类型必须是AndroidInjector.Factory类型;

  5. 如果方法使用了@Binds修饰并且方法参数有且仅有一个,当前方法参数类型必须是AndroidInjector.Factory的子类,这里的T表示AndroidInjectionKey或ClassKey注解的方法类型,如下案例:

      @Binds
      @IntoMap
      @ClassKey(GreenActivity.class)
      abstract AndroidInjector.Factory<?> bindBlueActivity(
           BlueActivityComponent.Builder builder);
      }
    

BlueActivityComponent.Builder是AndroidInjector.Factory子类

ContributesAndroidInjectorGenerator

ContributesAndroidInjector注解用于修饰方法,AndroidInjectorDescriptor.Validator完成对ContributesAndroidInjector注解校验,校验通过情况下使用ContributesAndroidInjectorGenerator类生成业务逻辑代码。

@ContributesAndroidInjector修饰的方法校验规则如下:

  1. 方法必须使用abstract修饰(按理说修饰的是接口方法也ok);

  2. 方法必须不能有参数;

  3. 方法的父级类必须是Module修饰的module节点;

  4. 该方法的返回类型不能使用泛型;

  5. ContributesAndroidInjector#modules里面的类必须使用@Module注解;

  6. 该方法不能使用Qualifier修饰的注解修饰;

以上条件都满足,接下来我们进行@ContributesAndroidInjector修饰的方法业务代码生成工作:*

  1. 生成的类名M1:@ContributesAndroidInjector修饰的方法所在module节点(如果module节点是内部类,外部"_"拼接当前module节点) + "-" +当前方法首字母大写后的名称;

  2. @ContributesAndroidInjector修饰的方法的返回类型 + "Subcomponent"生成一个S1类,作为M1类的内部类;在生成一个Factory作为S1的内部类;

  3. M1类添加@Module(subcomponents=M1类名.S1类名.class)注解,并且使用public abstract修饰,并且添加一个private无参构造函数;

  4. 添加bindAndroidInjectorFactory方法:

  • (1)方法名:bindAndroidInjectorFactory,abstract修饰;

  • (2)使用@Binds和@IntoMap注解修饰,并且使用@ClassKey(T.class)修饰,T表示@ContributesAndroidInjector修饰的方法返回类型;

  • (3)返回类型是AndroidInjector.Factory;

  • (4)参数名是builder,参数类型是S1类.Factory;

    1. 生成S1接口:
    • (1)添加Subcomponent注解;如果当前@ContributesAndroidInjector注解中包含modules值,那么S1类添加注解格式如下:@Subcomponent(modules = @ContributesAndroidInjector注解中包含modules值);

    • (2)生成的S1是一个接口,public修饰,如果@ContributesAndroidInjector注解的方法中使用了Scope修饰的注解,那么当前S1沿用该Scope修饰的注解;

    • (3)S1接口继承AndroidInjector,T表示@ContributesAndroidInjector修饰的方法返回类型;

    • (4)S1接口中添加Factory接口:

    • ① 接口名称是Factory,使用public static修饰,添加@Subcomponent.Factory注解;

    • ②Factory接口继承AndroidInjector.Factory,T表示@ContributesAndroidInjector修饰的方法返回类型。

    ComponentProcessor其他注解的讲解

    MapKey注解

    MapKeyProcessingStep类中实现具体的业务逻辑。

    @MayKey注解仅仅用于修饰注解。

    规则如下:

    1. 如果MapKey.unwrapValue() = true的情况下,被修饰的注解类方法有且仅有一个,并且该方法的返回类型不可以是TypeKind.ARRAY数组;

    2. 如果MapKey.unwrapValue() = false,被修饰的注解类方法可以有多个,并且当前项目必须引用com.google.auto.value.AutoAnnotation;

    生成代码:

    分为两种情况:

    1. 如果unwrapValue = false,使用AnnotationCreatorGenerator类完成业务逻辑,具体如下:
    • (1)类名 MapKey修饰的注解名称(如果该注解是内部类,那么使用"_"拼接直到当前注解) + "Creator";

    • (2)public final修饰该生成类,并且生成一个private修饰的无参构造函数;

    • (3)对当前 MapKey修饰的注解以及它的所有方法返回类型是注解(深入遍历所有注解)在当前生成类中生成方法:

    • ① 方法名:"create" + 当前注解名;

    • ② 方法使用AutoAnnotation注释,返回类型是注解类型;public statc修饰;

    • ③ 当前生成的方法参数是当前注解中所有方法的返回类型;

    • ④ 当前方法代码块:return new $T($L)T:"AutoAnnotation"+当前注解名称+""+当前方法名,T:"AutoAnnotation_" + 当前注解名称 + "_" + 当前方法名,L:参数以逗号分隔;(这里是为了符合AutoAnnotation注释生成规则);

    1. 如果unwrapValue = true(默认为true),并且MapKey修饰的注解中有且仅有的唯一方法返回类型还是一个注解,使用UnwrappedMapKeyGenerator类完成业务逻辑,具体如下:
    • 雷同于上面AnnotationCreatorGenerator类完成业务逻辑,唯一的不同是对MapKey修饰的注解的方法返回类型是注解(深入遍历所有注解)生成方法规则相同;这里我们看到和上面的区别在于没有包含MapKey修饰的注解。

    如果unwrapValue = true(默认就是true),并且唯一的方法返回类型不是注解类型,那么不需要做任何生成工作。这种也是非常常用的,而且不容易出错。

    ProductionComponent或ProductionSubcomponent注解

    如果使用的是Production(Sub)Component,那么还需要生成额外的代码,该代码的作用是监控。

    MonitoringModuleProcessingStep类中使用MonitoringModuleGenerator执行业务逻辑操作,生成一个类,规则如下:

    1. 类名是 component节点(如果是内部类,那么使用"_"拼接到当前component节点) 拼接 "_MonitoringModule",生成的类是抽象类,使用Module注解修饰;

    2. 添加private修饰的无参构造函数;

    3. 生成名为setOfFactories方法,该方法是抽象方法,Multibinds注解修饰该方法,方法返回类型是Set<ProductionComponentMonitor.Factory>;

    4. 生成名为monitor方法,返回类型是ProductionComponentMonitor,static修饰,使用Provides和ProductionScope注解修饰;

    • (1)添加两个参数component(类型是当前component节点)和factories(Set<ProductionComponentMonitor.Factory>);

    • (2)当前方法代码块:return Monitors.createMonitorForComponent(component, factories)

    总结

    内容不多,但是精确就好~后面会针对当前源码的整体架构以及全面理解Dagger注解文章。相当于分别从架构和实际开发角度对当前源码解析进行总结。

    可在QQ群:575306647 讨论

    源码解析github地址