SeamFramework.orgCommunity Documentation
Si è già visto come il modello di dependency injection di Web Beans consenta l'override dell'implementazione di un API a deployment time. Per esempio, il seguente Web Bean enterprise fornisce un'implementazione di un API PaymentProcessor
in produzione:
@CreditCard @Stateless
public class CreditCardPaymentProcessor
implements PaymentProcessor {
...
}
Ma in quest'ambiente di prova si procede con l'override dell'implementazione di PaymentProcessor
con un Web Bean differente:
@CreditCard @Stateless @Staging
public class StagingCreditCardPaymentProcessor
implements PaymentProcessor {
...
}
Quello che si è cercato di fare con StagingCreditCardPaymentProcessor
è sostituire completamente AsyncPaymentProcessor
in un particolare deployment del sistema. In tale deployment, il tipo di deploy @Staging
avrebbe più alta priorità del tipo di deploy di default @Production
, e quindi client con il seguente punto di iniezione:
@CreditCard PaymentProcessor ccpp
riceverebbero un'istanza di StagingCreditCardPaymentProcessor
.
Sfortunatamente ci sono parecchie trappole in cui è facile cadere:
il Web Bean con più alta priorità potrebbe non implementare tutti i tipi di API del Web Bean di cui tenta di fare override,
il Web Bean con più alta priorità potrebbe non dichiare tutti i tipi di binding del Web Bean di cui tenta di fare override,
il Web Bean con più alta priorità potrebbe non avere lo stesso nome del Web Bean di cui tenta di fare override, oppure
il Web Bean di cui tenta di fare override potrebbe dichiarare un metodo produttore, metodo distruttore o metodo osservatore.
In ciascuno di questi casi, il Web Bean di cui si tenta l'override potrebbe ancora venire chiamato a runtime. Quindi, l'override è qualcosa di incline all'errore per lo sviluppatore.
Web Beans fornisce una funzionalità speciale chiamata specializzazione, che aiuta lo sviluppatore ad evitare queste trappole. La specializzazione sembra inizialmente un pò esoterica, ma in pratica è facile da usare, e si apprezzerà veramente la sicurezza extra che fornisce.
La specializzazione è una funzionalità specifica dei Web Bean semplici ed enterprise. Per fare uso della specializzazione il Web Bean a più alta priorità deve:
essere un diretta sottoclasse del Web Bean di cui fa l'override, e
essere un semplice Web Bean se il Web Bean di cui fare override è un semplice Web Bean o un Web Bean Enterprise se il Web Bean di cui fa override è un Web Bean Enterprise, e
essere annotato con @Specializes
.
@Stateless @Staging @Specializes
public class StagingCreditCardPaymentProcessor
extends CreditCardPaymentProcessor {
...
}
Si dice che il Web Bean a più alta priorità specializza la sua superclasse.
Quando viene usata la specializzazione:
i tipi di binding della superclasse vengono automaticamente ereditati dal Web Bean annotato con @Specializes
, e
il nome del Web Bean della superclasse è automaticamente ereditato dal Web Bean annotato con @Specializes
, e
i metodi produttori, metodi distruttori e metodi osservatori dichiarati dalla superclasse vengono chiamati da un'istanza del Web Bean annotato con @Specializes
.
Nel nostro esempio, il tipo di binding @CreditCard
di CreditCardPaymentProcessor
viene ereditato da StagingCreditCardPaymentProcessor
.
Inoltre il manager Web Bean validerà che:
tutti i tipi di API della superclasse sono tipi di API del Web Bean annotato con @Specializes
(tutte le interfacce locali del bean enterprise della superclasse sono anch'essi interfacce della sottoclasse),
il tipo di deploy di un Web Bean annotato con @Specializes
ha una precedenza più alta di un tipo di deploy della superclasse, e
non esiste nessun altro Web Bean che specializza la superclasse.
Se una di queste condizioni viene violata, il manager Web Bean lancia un'eccezione in fase di inizializzazione.
Quindi, si può essere certi che la superclasse non verrà mai chiamata in alcun deploy del sistema in cui viene deployato ed abilitato il Web Bean annotato con @Specializes
.