2016-03-06 18 views
8

Supponiamo che io sto costruendo una macchina e ho diversi fagioli freno con diverse implementazioniDagger2 personalizzato @Qualifier utilizzo

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

perché il mio CarModule deve definire @Provides per i tipi di freni specifici? Non dovrebbe essere sufficiente il tipo di annotazione personalizzata @BrakeType per determinare quale impl iniettare? O richiederebbe l'uso della riflessione, che dagger2 non usa?

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

risposta

0

La riflessione non è probabilmente un grosso problema qui perché accadrebbe in fase di compilazione.

Non ho guardato attraverso il source code, ma il pugnale è ma un processore di annotazione — si registra per essere chiamato ogni volta che viene utilizzata una serie di annotazioni date. Mentre il qualificatore da solo sarebbe probabilmente sufficiente per scoprire cosa intendessi, posso pensare ai seguenti motivi per cui questa non potrebbe essere la soluzione migliore.

javax.inject.Qualifier fa parte di un'API più grande e potrebbe anche essere utilizzato da altre librerie in un contesto diverso. Quindi potresti non volere che il pugnale generi codice per un metodo, solo perché è annotato con un qualificatore. Un altro motivo potrebbe essere che, poiché esiste la possibilità di creare qualificatori personalizzati, il pugnale dovrebbe controllare ogni annotazione su ogni metodo in ogni modulo e quindi a sua volta determinare se l'annotazione stessa è annotata con @Qualifier per vedere se il metodo è di un certo interesse ad esso. Questo è piuttosto un sovraccarico non necessario.

Ci potrebbero essere più motivi, ma quelli 2 elencati qui sembrano sufficienti per far sì che gli utenti di pugnale usino una specie di contratto: @Provides.

Le annotazioni non influiscono sulle prestazioni del codice e l'aggiunta di un'annotazione aggiuntiva non causerà alcun danno, quindi c'è molto altro da guadagnare che perdere maneggiandolo nel modo in cui lo fanno.

3

Il pugnale non esamina le annotazioni del qualificatore sulle classi, solo sui metodi @Provides o @Binds. Quindi le annotazioni @BrakeType(value="abs") sulle tue classi non hanno alcun effetto.

Un modo più canonico di scrittura del codice è:

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); 
} 

Nota che poiché avete @Inject sui costruttori di implementazioni, si può semplicemente utilizzare il pugnale di @Bind per legare le implementazioni direttamente all'interfaccia adeguatamente qualificato .

1

Per il record, è possibile utilizzare le proprie annotazioni di qualificatore (come BrakeType), oppure utilizzare @Named da Dagger. Usando questo ultimo, il codice sarà simile:

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

E sul modulo:

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

ricordarsi di utilizzare le convenzioni di nome Dagger (come fornire prefisso) per ottenere la maggior parte di esso. E sui tuoi moduli prova ad usare tutti i metodi @Provides statici, così facendo l'implementazione risultante non ha bisogno di istanziarla.

In breve, Fornisce e qualificatori lavorano insieme quindi è necessario entrambi.


Fonte: Dagger users guide.

0

@Inject constructor inidonee a fornire un tipo che classe stessa, nel tuo caso, che dire si fornisce il tipo AbsBrakeImpl e BrakeImpl tipo, in modo che quando si tenta di iniettare con Brake, pugnale non può trovare il provider.

Il qualificatore in @Inject constructor non funziona, perché il tipo di classe è univoco, non è necessario aggiungere un qualificatore a.

Così, nel vostro caso, o si deve usare CarModule per raccontare Dagger esplicitamente, o cambiare la tua costruttore con

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