前言
前面主要针对component及其关联的subcomponent、module、bindingMethod、Inject等核心注解的解析。这里针对AndroidProcessor注解梳理以及ComponentProcessor中其他注解例如MapKey注解梳理
AndroidProcessor注解
AndroidMapKeyValidator类对AndroidInjectionKey和ClassKey注解的校验,这两个注解是使用MapKey注解修饰的注解;
ContributesAndroidInjectorGenerator类是针对ContributesAndroidInjector注解校验,以及代码生成。
AndroidMapKeyValidator
针对AndroidInjectionKey和ClassKey注解的校验。
AndroidInjectionKey注解只能修饰方法,ClassKey注解可以修饰方法和变量。
这里针对的是AndroidInjectionKey或ClassKey修饰方法校验,规则如下:
-
如果方法使用了AndroidInjectionKey或ClassKey修饰,那么当前方法不能使用Qualifier修饰的注解修饰;
-
方法返回类型如果不是AndroidInjector.Factory及其子类,不需要继续校验了,该方法直接被忽略;
-
如果该方法使用了Scope注解修饰的注解修饰,该方法必须使用@SuppressWarnings注解修饰,并且该@SuppressWarning注解包含dagger.android.ScopedInjectorFactory值;
-
方法返回类型必须是AndroidInjector.Factory类型;
-
如果方法使用了@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修饰的方法校验规则如下:
-
方法必须使用abstract修饰(按理说修饰的是接口方法也ok);
-
方法必须不能有参数;
-
方法的父级类必须是Module修饰的module节点;
-
该方法的返回类型不能使用泛型;
-
ContributesAndroidInjector#modules里面的类必须使用@Module注解;
-
该方法不能使用Qualifier修饰的注解修饰;
以上条件都满足,接下来我们进行@ContributesAndroidInjector修饰的方法业务代码生成工作:*
-
生成的类名M1:@ContributesAndroidInjector修饰的方法所在module节点(如果module节点是内部类,外部"_"拼接当前module节点) + "-" +当前方法首字母大写后的名称;
-
@ContributesAndroidInjector修饰的方法的返回类型 + "Subcomponent"生成一个S1类,作为M1类的内部类;在生成一个Factory作为S1的内部类;
-
M1类添加@Module(subcomponents=M1类名.S1类名.class)注解,并且使用
public abstract修饰,并且添加一个private无参构造函数; -
添加bindAndroidInjectorFactory方法:
-
(1)方法名:bindAndroidInjectorFactory,abstract修饰;
-
(2)使用@Binds和@IntoMap注解修饰,并且使用@ClassKey(T.class)修饰,T表示@ContributesAndroidInjector修饰的方法返回类型;
-
(3)返回类型是AndroidInjector.Factory;
-
(4)参数名是builder,参数类型是S1类.Factory;
- 生成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修饰的方法返回类型。
-
如果MapKey.unwrapValue() = true的情况下,被修饰的注解类方法有且仅有一个,并且该方法的返回类型不可以是TypeKind.ARRAY数组;
-
如果MapKey.unwrapValue() = false,被修饰的注解类方法可以有多个,并且当前项目必须引用com.google.auto.value.AutoAnnotation;
- 如果unwrapValue = false,使用AnnotationCreatorGenerator类完成业务逻辑,具体如下:
-
(1)类名 MapKey修饰的注解名称(如果该注解是内部类,那么使用"_"拼接直到当前注解) + "Creator";
-
(2)public final修饰该生成类,并且生成一个private修饰的无参构造函数;
-
(3)对当前 MapKey修饰的注解以及它的所有方法返回类型是注解(深入遍历所有注解)在当前生成类中生成方法:
-
① 方法名:"create" + 当前注解名;
-
② 方法使用AutoAnnotation注释,返回类型是注解类型;public statc修饰;
-
③ 当前生成的方法参数是当前注解中所有方法的返回类型;
-
④ 当前方法代码块:
return new $T($L),L:参数以逗号分隔;(这里是为了符合AutoAnnotation注释生成规则); - 如果unwrapValue = true(默认为true),并且MapKey修饰的注解中有且仅有的唯一方法返回类型还是一个注解,使用UnwrappedMapKeyGenerator类完成业务逻辑,具体如下:
- 雷同于上面AnnotationCreatorGenerator类完成业务逻辑,唯一的不同是对MapKey修饰的注解的方法返回类型是注解(深入遍历所有注解)生成方法规则相同;这里我们看到和上面的区别在于没有包含MapKey修饰的注解。
-
类名是 component节点(如果是内部类,那么使用"_"拼接到当前component节点) 拼接 "_MonitoringModule",生成的类是抽象类,使用Module注解修饰;
-
添加private修饰的无参构造函数;
-
生成名为setOfFactories方法,该方法是抽象方法,Multibinds注解修饰该方法,方法返回类型是Set<ProductionComponentMonitor.Factory>;
-
生成名为monitor方法,返回类型是ProductionComponentMonitor,static修饰,使用Provides和ProductionScope注解修饰;
-
(1)添加两个参数component(类型是当前component节点)和factories(Set<ProductionComponentMonitor.Factory>);
-
(2)当前方法代码块:
return Monitors.createMonitorForComponent(component, factories);
ComponentProcessor其他注解的讲解
MapKey注解
MapKeyProcessingStep类中实现具体的业务逻辑。
@MayKey注解仅仅用于修饰注解。
规则如下:
生成代码:
分为两种情况:
如果unwrapValue = true(默认就是true),并且唯一的方法返回类型不是注解类型,那么不需要做任何生成工作。这种也是非常常用的,而且不容易出错。
ProductionComponent或ProductionSubcomponent注解
如果使用的是Production(Sub)Component,那么还需要生成额外的代码,该代码的作用是监控。
MonitoringModuleProcessingStep类中使用MonitoringModuleGenerator执行业务逻辑操作,生成一个类,规则如下:
总结
内容不多,但是精确就好~后面会针对当前源码的整体架构以及全面理解Dagger注解文章。相当于分别从架构和实际开发角度对当前源码解析进行总结。
可在QQ群:575306647 讨论