簡體   English   中英

Dagger2自定義@Qualifier用法

[英]Dagger2 custom @Qualifier usage

假設我正在制造一輛汽車,我有幾個不同實施的剎車豆

class Car {
    @Inject
    Car(@BrakeType(value="abs")Brake frontBrake, @BrakeType(value="nonabs")Brake rearBrake) { }
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface BrakeType {
    String value();
}

interface Brake {}

@BrakeType(value="abs")
class AbsBrakeImpl implements Brake {
    @Inject AbsBrakeImpl() {}
}

@BrakeType(value="nonabs")
class BrakeImpl implements Brake {
    @Inject BrakeImpl() {}
}

為什么我的CarModule必須為特定的制動類型定義@Provides? 自定義注釋類型@BrakeType不應該足以確定要注入哪個impl? 或者這需要使用反射,dagger2不使用?

@Module
public class CarModule {
    @Provides @BrakeType("abs")
    public Brake absBrake() {
        return new AbsBrakeImpl();
    }
    @Provides @BrakeType("nonabs")
    public Brake nonabsBrake() {
        return new BrakeImpl();
    }
}

Dagger不會在類上查看限定符注釋,只能查看@Provides@Binds方法。 所以類上的@BrakeType(value="abs")注釋沒有任何效果。

編寫代碼的更規范的方法是:

class AbsBrakeImpl implements Brake {
    @Inject AbsBrakeImpl() {}
}

class BrakeImpl implements Brake {
    @Inject BrakeImpl() {}
}

@Module
abstract class CarModule {
    @Binds @BrakeType("abs")
    abstract Brake absBrake(AbsBrakeImpl impl);

    @Binds @BrakeType("nonabs")
    abstract Brake nonabsBrake(BrakeImpl impl);
}

請注意,由於您在實現的構造函數上有@Inject ,因此您可以簡單地使用Dagger的@Bind將實現直接綁定到適當的限定接口。

對於記錄,您可以使用自己的限定符注釋(作為BrakeType),或者只使用Dagger中的@Named。 使用最后一個,您的代碼將類似於:

@Inject @Named("abs") Brake frontBrake;
@Inject @Named("nonabs") Brake rearBrake;

在你的模塊上:

@Provides @Named("abs") static Brake provideAbsBrake() {
    return new AbsBrakeImpl();
}
@Provides @Named("nonabs") static Brake provideNonAbsBrake() {
    return new BrakeImpl();
}

請記住使用Dagger名稱約定(如提供前綴)來獲取大部分內容。 在你的模塊上嘗試使用所有@Provides方法靜態,這樣做結果實現不需要實例化它。

簡而言之,提供和限定符一起工作,因此您需要兩者。


來源: Dagger用戶指南

@Inject constructor意味着提供一個類本身,在您的情況下,這意味着您提供AbsBrakeImpl類型和BrakeImpl類型,因此當您嘗試注入Brake ,dagger無法找到提供者。

@Inject constructor限定符不起作用,因為類類型是唯一的,我們不需要添加限定符。

因此,在您的情況下,或者您必須使用CarModule明確地告訴Dagger,或者更改您的構造函數

class Car {
    @Inject
    Car(AbsBrakeImpl frontBrake, BrakeImpl rearBrake) { }
}

反思可能不是一個大問題,因為它會在編譯時發生。

我沒有查看源代碼 ,但是dagger只是一個注釋處理器 - 只要使用一組給定的注釋,它就會被調用。 雖然單憑限定符可能足以找出你的意圖,但我可以想到以下原因,為什么這不是最好的解決方案。

javax.inject.Qualifier是更大的API的一部分,也可能被不同上下文中的其他庫使用。 所以你可能不希望匕首為方法生成代碼,只是因為它是用限定符注釋的。

另一個原因可能是因為有可能創建自定義限定符,所以dagger必須檢查每個模塊中每個方法的每個注釋,然后依次確定該注釋本身是否使用@Qualifier注釋以查看該方法是否屬於某些方法它的興趣。 這是一個不必要的開銷。

可能有更多的原因,但這里列出的2個似乎足以讓匕首用戶使用某種合同: @Provides

注釋不會影響代碼的性能,並且使用附加注釋不會造成任何傷害,因此通過按照它們的方式處理它會有更多的損失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM