2014-04-10 18 views
10

Sto utilizzando CDI come framework di iniezione, ma ho trovato alcune limitazioni nel suo utilizzo, e questo è uno di questi. Sto cercando di inizializzare la creazione di un'istanza di bean con i valori di runtime. Esempio:Passa il parametro all'istanza di @Inject Bean

Si prega di notare che "a" è una costante nell'esempio, ma in pratica è una variabile; Io chiarisco questo in modo da non pubblicare una risposta con un @Producer per iniettare il valore allora nel costruttore di MyNumber.

Ora, qualcuno ha un'idea di come posso farlo?

risposta

4

In base alle specifiche, non è possibile avere un bean con un costruttore non semplice, "non inietto" ( 3.1. Managed beans,).

Pertanto, i modi per impostare i parametri devono avere il setMethod() per loro, renderli come campi @Inject nel bean o annotare il costruttore con l'annotazione @Inject e rendere i parametri del costruttore da iniettare ( 5.5.1. Injection using the bean constructor)

Spero di aver risposto alla domanda.

10

Non sono sicuro di cosa si sta provando a fare, ma da quello che capisco si desidera inizializzare il bean con i dati nell'annotazione del punto di iniezione o in fase di esecuzione tramite la ricerca programmatica. È possibile farlo utilizzando InjectionPoint meta dati nel vostro fagioli (l'unico vincolo sarà quello di mettere il fagiolo in ambito dipendente)

si può fare qualcosa di simile.

Prima creare un qualificatore con un valore non vincolante.

@Qualifier 
@Target({TYPE, METHOD, PARAMETER, FIELD}) 
@Retention(RUNTIME) 
@Documented 
public @interface Initialized { 

    @Nonbinding int value() default 0; // int value will be store here 
} 

si deve aggiungere questo qualificatore sul tuo fagioli e analizzare InjectionPoint al momento della creazione.

@Initialized 
public class MyNumber { 
    int number; 

    private int extractValue(InjectionPoint ip) { 
    for (Annotation annotation : ip.getQualifiers()) { 
     if (annotation.annotationType().equals(Initialized.class)) 
      return ((Initialized) annotation).value(); 
    } 
    throw new IllegalStateException("No @Initialized on InjectionPoint"); 
    } 

    @Inject 
    public MyNumber(InjectionPoint ip) { 
     this.number = extractValue(ip); 
    } 

    public String toString() { 
     return "Your number is: " + number; 
    } 
} 

Ora è possibile iniettare un numero inizializzato in questo modo:

@Inject 
@Initialized(8) 
MyNumber number; 

Se si vuole decidere il valore di inizializzazione in fase di esecuzione, dovrete usare ricerca programmatica:

Innanzitutto creare l'annotazione letterale `@ Initialized``

public class InitializedLiteral extends AnnotationLiteral<Initialized> implements Initialized { 

    private int value; 

    public InitializedLiteral(int value) { 
     this.value = value; 
    } 

    @Override 
    public int value() { 
     return value; 
    } 
} 

Quindi è possibile utilizzare Instance per creare il tuo bean.

public class ConsumingBean { 

    @Inject 
    @Any 
    Instance<MyNumber> myNumberInstance; 

    public MyNumber getMyNumberBeanFor(int value) { 
    return myNumberInstance.select(new InitializedLiteral(value)).get(); 
    } 
    ... 
} 

Ricordare questo funziona solo se MyNumber è portata dipendente che ha senso perché è l'unico modo per modificare il valore di inizializzazione per ogni iniezione.

+0

molto buono, +1, il mio voto !!! :) – Delfino

+0

@Antoine, l'esempio che hai fornito sta funzionando bene, ma se ci può essere flessibilità come saltare l'annotazione Inizializzata mentre si inietta la classe MyNumber da alcune classi se non è necessario passare il parametro? –

Problemi correlati