Dagger2自定义@Qualifier用法

Rog*_* H. 12 java dagger-2

假设我正在制造一辆汽车,我有几个不同实施的刹车豆

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() {}
}
Run Code Online (Sandbox Code Playgroud)

为什么我的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*der 7

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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于您拥有@Inject实现的构造函数,因此您可以简单地使用Dagger @Bind将实现直接绑定到适当的限定接口.


Dav*_*jak 1

反射在这里可能不是一个大问题,因为它会在编译时发生。

我没有查看源代码,但 dagger 只是一个注释处理器——它注册为在使用一组给定注释时被调用。虽然仅限定符可能足以找出您的意图,但我可以想到以下原因为什么这不是最佳解决方案。

javax.inject.Qualifier是更大 API 的一部分,也可能被其他库在不同的上下文中使用。因此,您可能不希望 dagger 为方法生成代码,只是因为它用限定符注释。

另一个原因可能是,由于可以创建自定义限定符,因此 dagger 必须检查每个模块中每个方法的每个注释,然后依次确定该注释本身是否被注释,以查看@Qualifier该方法是否对该方法感兴趣。它。这是不必要的开销。

可能还有更多原因,但这里列出的这两个似乎足以让 dagger 用户使用某种合同:@Provides

注释不会影响代码的性能,并且附加注释不会造成任何损害,因此按照它们的方式处理它利大于弊。