[英]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.