Suppose I'm building a car and I have several Brake beans with different implementations
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() {}
}
why does my CarModule have to define @Provides for the specific Brake types? Shouldn't the custom annotation type @BrakeType be enough to determine which impl to inject? Or would that require using reflection, which dagger2 does not use?
@Module
public class CarModule {
@Provides @BrakeType("abs")
public Brake absBrake() {
return new AbsBrakeImpl();
}
@Provides @BrakeType("nonabs")
public Brake nonabsBrake() {
return new BrakeImpl();
}
}
Dagger doesn't look at qualifier annotations on classes, only on @Provides
or @Binds
methods. So the @BrakeType(value="abs")
annotations on your classes don't have any effect.
A more canonical way of writing your code is:
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);
}
Note that since you have @Inject
on the constructors of your implementations, you can simply use Dagger's @Bind
to bind the implementations directly to the appropriately qualified interface.
Reflection is probably not a big issue here because it would happen at compile time.
I did not look through the source code, but dagger is but an annotation processor—it registers to be called whenever a set of given annotations is used. While the qualifier alone would probably be enough to find out what you intended, I can think of the following reasons why this could not be the best solution.
javax.inject.Qualifier
is part of a bigger API, and might also be used by other libraries in different context. So you might not want dagger to generate code for a method, just because it is annotated with a qualifier.
Another reason could be that since there is the possibility to create custom qualifiers, dagger would have to check every annotation on every method in every module and then in turn determine whether that annotation itself is annotated with @Qualifier
to see if the method is of some interest to it. This is rather an unnecessary overhead.
There might be more reasons, but those 2 listed here seem enough to just make users of dagger use some sort of contract: @Provides
.
Annotations don't affect the performance of the code, and having an addtional annotation won't do any harm, so there is more to gain than to lose by handling it the way they do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With