Dagger2解析5-Qualifier

Dagger2系列:

  1. Dagger2解析-1
  2. Dagger2解析2-Component的依赖关系
  3. Dagger2解析3-SubComponent
    4.Dagger2解析4-Scope

Dagger版本:2.11

在第二篇Dagger2解析2-Component的依赖关系中曾经提到过,一个组件中依赖关系中不能有相同类型的提供者(构造函数标注@Inject的可创建实例的对象或者module里标注@Provides的方法),否则会出现依赖迷失的错误,而编译时判断的依据就是类型是否重复,可是有些时候就是会出现类型相同的不同实例时又该如何解决呢,这里就需要用到本篇的主角Qualifier(限定符)了

通过限定符,可以从多个提供相同类型的Provider中找出正确的那个

老样子,先看Qualifier类

package javax.inject;
// ......
/**
 *Identifies qualifier annotations. Anyone can define a new qualifier. A
 * qualifier annotation:
 * ......
 */
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
@Documented
public @interface Qualifier {}

Qualifier同样是javax.inject包下的一个注解类,和Scope类似,也是能够自定义的

1.示例

代码撸起,还是老朋友Target和Member,这次Module会有多个提供Member的方法

class Member(val name: String)

class Target {

    @field:[Inject CustomQualifier(name = "A")]
    lateinit var memberA: Member

    @field:[Inject CustomQualifier(name = "B")]
    lateinit var memberB: Member
}

@Module
class MemberModule {
    @CustomQualifier(name = "A")
    @Provides
    fun provideMemberA(): Member = Member("by provideMemberA")

    @CustomQualifier(name = "B")
    @Provides
    fun provideMemberB(): Member = Member("by provideMemberB")
}

@Component(modules = arrayOf(MemberModule::class))
interface TargetComponent {
    fun inject(target: Target)
}

ps:用java的无视就好,关于Target中的两个成员变量memberAmemberB遇到点小坑,之前直接这么写的

    @Inject 
    @CustomQualifier(name = "A")]
    lateinit var memberA: Member

    @Inject 
    @CustomQualifier(name = "B")]
    lateinit var memberB: Member

一直编译不通过,提示找不到能提供实例的provider,后来在stackoverflow上找到一篇解答,才发现kotlin里属性的标注要用@field:[/* 和成员变量相关的注解放在这 */]

2. 代码分析

由于例子简单,和 Dagger2解析-1的相比也不过就多了一个工厂,事实上,这两个工厂的代码也是几乎一样的,唯一不同的是get方法调用的module对应的两个provide方法

public final class MemberModule_ProvideMemberAFactory implements Factory<Member> {
  //...
  @Override
  public Member get() {
    return Preconditions.checkNotNull(
        // 调用的是module的provideMemberA
        module.provideMemberA(), "Cannot return null from a non-@Nullable @Provides method");
  }
  //...
}

public final class MemberModule_ProvideMemberBFactory implements Factory<Member> {
  // ...
  @Override
  public Member get() {
    return Preconditions.checkNotNull(
        // 调用的是module的provideMemberB
        module.provideMemberB(), "Cannot return null from a non-@Nullable @Provides method");
  }
  // ...
}

然后是Injector

public final class Target_MembersInjector implements MembersInjector<Target> {
  private final Provider<Member> memberAProvider;
  private final Provider<Member> memberBProvider;
  //...
  @Override
  public void injectMembers(Target instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    // complier生成代码时通过限定符注解成功找到了对应的提供依赖的provider
    instance.memberA = memberAProvider.get();
    instance.memberB = memberBProvider.get();
  }
}

可以看到,代码上并没有什么奇怪的操作,所以说明这个注解提供给编译器生成代码后就没啥用了,其他的也没啥好说的了,通过对module和需要被注入的依赖上标注限定符,编译器在发现重复的Provider时,就能通过限定符去寻找正确的Provider了

ps1:关于注解不太明白,retention保留的问题,照实现原理看,这些注解,包括@Component @Module @Scope以及本篇的@Qualifier都应该不需要在运行期保留啊,但写法都是@Retention(RetentionPolicy.RUNTIME)?望大佬指明
ps2:关于kotlin的注解类annotation class,它的Retention默认就是RUNTIME,所以可以不写,例如本篇中的CustomQualifier可以写成

@Qualifier
annotation class CustomQualifier(val name: String = "")

3.总结

1.这个注解是用来解决依赖迷失的,适合注入对象需要多个同类型依赖的场合,视情况个人觉得Scope也能拿来解决这个问题
2.和前面的注解不同,kotlin上用要注意把相关注解写在@field[]里,不然无效

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容