public String finishWithCash() {
paymentChoosed = paymentsLazy.select(Cash.class).get();
return paymentChoosed.pay();
}
CDI Dynamic Inject
Introdução
As vezes precisamos escrever várias implementações para uma interface de regras de negócios, para aumentar o desacoplamento vamos injetar dinamicamente a implementação em tempo de execução.
Exemplo 1
Neste exemplo, temos uma interface Payment
e suas implementações:
-
Cash
-
CreditCard
Em nosso teste (FinalizePaymentTest
) nós injetamos a classe FinalizePayment, e chamamos o método finishWithCash
.
Esse método irá injetar dinamicamente a implementação correta usando os recursos do CDI
observe que está sendo usado uma variável chamada de paymentsLazy
essa variável irá conter todas as implementações da interface Payment
@Inject
@Any
private Instance<Payment> paymentsLazy;
Nessa variável estamos usando:
-
Anotação
@inject
Indica ao CDI que gostariamos de realizar um injeção de dependencia
-
Anotação
@Any
Indicar que deve ser listada todas as implementações possíveis.
-
Objeto
Instance
Objeto responsável por conhecer todas as implementações possíveis e instancia-las no momento desejado.
com essa variável pronta podemos chama-la usando o:
paymentsLazy.select(Cash.class).get();
onde Cash.class
informa qual e a implementação e .get()
retorna a instancia pronta para uso.
Exemplo 2
Neste exemplo, temos uma interface Payment
e suas implementações:
-
Cash
-
CreditCard
Em nosso teste (FinalizePaymentQualifierTest
) nós injetamos a classe FinalizePayment, e chamamos o método finishByQualifier
.
Esse método irá injetar dinamicamente a implementação correta usando um Qualifier
(PaymentType).
public String finishByQualifier(PaymentType type) {
paymentChoosed = paymentsLazy.select( new PayByQualifier(type) ).get();
return paymentChoosed.pay();
}
Para essa abordagem funcionar precisaremos criar uma nova classe chamada PayByQualifier
que extende AnnotationLiteral
que espera a passagem de um qualifier em seu parametro T extends Annotation
(Generics).
public class PayByQualifier extends AnnotationLiteral<PaymentQualifier> implements PaymentQualifier {
private PaymentType type;
public PayByQualifier(PaymentType type) {
this.type = type;
}
@Override
public PaymentType type() {
return this.type;
}
}
o importante e implementar o método da Anotação em nosso caso o public PaymentType type();
Para faciliar essa implementação recebemos esse valor por construtor de nossa nova classe
public PayByQualifier(PaymentType type) {
this.type = type;
}
Com essa classe pronta podemos usa-la em nossa classe de negócio:
paymentChoosed = paymentsLazy.select( new PayByQualifier(type) ).get();
Obs: A estrutura de qualifier foi reaproveitada do project https://github.com/cassunde/tomee/tree/master/examples/cdi-qualifier