Desenvolvendo uma aplicação Desktop com Weld – Final
Depois da parte 1 e parte 2, chegamos à parte final do nosso exemplo. Disponibilizei o código e vou mostrar mais algumas coisas.
Só uma observação sobre o código: é o mesmo utilizado na apresentação de 14 de Novembro de 2009, quando ainda não tínhamos as mesmas versões de hoje. Mas o exemplo é totalmente funcional. Acabei deixando fixa a versão no pom.xml, então para testar a última versão você vai ter que alterá-lo.
Agora voltando ao post…
Alternatives
Alternatives são a forma de trocarmos um objeto por outro. É parecido com um decorator, mas em vez de incrementar funcionalidades, um alternative serve para substituir um bean.
No nosso exemplo, temos o seguinte objeto como alternativa ao nosso CaixaEletronico:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Alternative public class CaixaEletronicoSubstituto extends CaixaEletronico{ public void depositar(float valor) { System.out.println("@@@@@@ CaixaEletronicoMock.depositar():" + valor); } public void sacar(float valor) { System.out.println("@@@@@@ CaixaEletronicoMock.sacar():" + valor); } } |
E para habilitar temos que mudar novamente nosso META-INF/beans.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> <interceptors> <class>br.com.jugms.weldse.intercept.ContaInterceptor</class> </interceptors> <decorators> <class>br.com.jugms.weldse.intercept.CaixaDecorator</class> </decorators> <alternatives> <class>br.com.jugms.weldse.model.CaixaEletronicoSubstituto</class> </alternatives> </beans> |
Agora se executarmos nosso código a saída sera:
hello CaixaDecorator.sacar() @@@@@@ CaixaEletronicoMock.sacar():200.0 ContaInterceptor.protege(antes) >> getSaldo ContaInterceptor.protege(depois) >> getSaldo 2000.0 CaixaDecorator.depositar() @@@@@@ CaixaEletronicoMock.depositar():300.0 ContaInterceptor.protege(antes) >> getSaldo ContaInterceptor.protege(depois) >> getSaldo 2000.0
Como podemos ver, nosso decorator decora o alternative e o interceptor continua funcionando normalmente.
Podemos também declarar uma anotação própria e anotá-la como alternative. Mas em vez de tentar explicar, vou mostrar um outro exemplo que servirá como base para este.
Estereótipos próprios
Podemos criar nossos próprios estereótipos, e dessa forma não só reduzir a quantidade de anotações em cima dos nossos beans, mas também deixar a leitura das anotações mais condizentes com nosso linguajar do dia a dia.
Vamos pegar como exemplo o nosso objeto ContaBancaria:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package br.com.jugms.weldse.model; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; import javax.inject.Named; import br.com.jugms.weldse.intercept.Seguro; @ApplicationScoped @Seguro public class ContaBancaria { //o código já foi visto antes } |
Já vimos este código e o corpo da classe não tem relação com o que vamos ver agora. Agora o mais importante é observarmos as anotações. Temos duas, mas poderíamos ter mais. Para deixar isso mais limpo e com mais significado no meu negócio, poderia criar um estereótipo próprio como o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package br.com.jugms.weldse.model; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Stereotype; import br.com.jugms.weldse.intercept.Seguro; @ApplicationScoped @Seguro @Stereotype @Target(TYPE) @Retention(RUNTIME) public @interface JavaneirosBean { } |
E depois mudar nosso ContaBancaria deixando ele assim:
1 2 3 4 5 6 7 8 9 10 | package br.com.jugms.weldse.model; import javax.enterprise.event.Observes; import javax.inject.Inject; import javax.inject.Named; @JavaneirosBean public class ContaBancaria { //o código já foi visto antes } |
Com isso o resultado será o mesmo de antes. Nosso objeto ContaBancaria é @Seguro e @ApplicationScoped. Além disso se depois quisermos dizer que nosso @JavaneirosBean é também um @Alternative ou qualquer outro estereótipo pré-existente ou mesmo um outro estereótipo customizado, basta anotar nossa anotação @JavaneirosBean com a anotação desejada.
Pode parecer estranho usarmos anotações de anotações, mas para exemplificar, se a JPA suportasse isso eu poderia ter uma anotação @Entidade que seria uma @Entity (JPA) e ao mesmo tempo @Named (CDI) e assim poder utilizá-la diretamente nas minhas view JSF com uma única anotação.
Conceitos gerais
Eu disse que ao final do exemplo iria entrar mais na parte teórica de como a CDI trata mais extamente a injeção de dependência, seleção de candidatos etc. Porém por questão de organização, vou deixar isso em um post separado.
Recent Comments