Dagger2自定义@Qualifier用法

时间:2016-03-06 16:43:15

标签: 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() {}
}

为什么我的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();
    }
}

4 个答案:

答案 0 :(得分:6)

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将实现直接绑定到适当的合格接口。

答案 1 :(得分:1)

对于记录,您可以使用自己的限定符注释(如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 users guide

答案 2 :(得分:1)

@Inject constructor表示在您的情况下提供类本身的类型,这意味着您提供AbsBrakeImpl类型和BrakeImpl类型,因此当您尝试注入{{1}时},dagger无法找到提供者。

Brake中的限定符不起作用,因为类类型是唯一的,我们不需要添加限定符。

因此,在您的情况下,或者您必须使用@Inject constructor明确告诉Dagger,或者使用

更改构造函数
CarModule

答案 3 :(得分:0)

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

我没有查看source code,但是dagger只是一个注释处理器 - 只要使用一组给定的注释,它就会被注册。虽然单凭限定符可能足以找出你的意图,但我可以想到以下原因,为什么这不是最佳解决方案。

total = 12 print ("I will play a game, you will choose 1, 2, or 3, and I will do the same, and I should always win, do you want to play?") yesnoA = input("Yes or No?") if yesnoA == yes: print ("Yay, your turn!") turnAA = input('Your First Move') if turnAA == 1: print ("I choose 3") total = total - 4 print ("Total = ",total) else: if turnAA == 2: print ("I choose 2") total = total - 4 print ("Total = ",total) else: if turnAA == 3: print ("I choose 1") total = total - 4 print ("Total = ",total) else: print ("Cheater, try again") else: yesnoB = input("Ok, you sure?") if yesnoB == yes: print ("Yay, your turn") turnAA = input('Your First Move') if turnAA == 1: print ("I choose 3") total = total - 4 print ("Total = ",total) else: if turnAA == 2: print ("I choose 2") total = total - 4 print ("Total = ",total) else: if turnAA == 3: print ("I choose 1") total = total - 4 print ("Total = ",total) else: print ("Cheater, try again") else: print ("Well, goodbye") 是更大的API的一部分,也可能在不同的上下文中被其他库使用。所以你可能不希望匕首为方法生成代码,只是因为它是用限定符注释的。

另一个原因可能是因为有可能创建自定义限定符,dagger必须检查每个模块中每个方法的每个注释,然后依次确定是否用Yes or No?yes Traceback (most recent call last): File "C:/Users/*user*/Desktop/Code/Python/Nim Game.py", line 5, in <module> if yesnoA == yes: NameError: name 'yes' is not defined 注释该注释本身才能看到如果该方法对它有一定的兴趣。这是一个不必要的开销。

可能有更多原因,但这里列出的2个似乎足以让匕首用户使用某种合同:javax.inject.Qualifier

注释不会影响代码的性能,并且使用附加注释不会造成任何伤害,因此通过像处理它一样处理它会有更多的损失。