AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
AOP – AspectJ 1.5.4 Programação Orientada a Aspectos
Diego Pacheco Dezembro/2007
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Sumário 1. Conceitos Básicos sobre AOP ........................ Error! Bookmark not defined.-1 Objetivos .................................................................................................................................... 0 Conceitos Básicos .................................................................................................................. 0 Concerns VS Crosscuting Concerns ............................................................................ 0 Aspectos .................................................................................................................................... 0 Pilares do AspectJ ............................................................................................................... 0 Mecanismos de Weaving ................................................................................................... 0 Exercícios ............................................................................................................................... 0 2. Join Points e Pointcuts ....................................... Error! Bookmark not defined. Objetivos .................................................................................................................................... 0 Pointcuts................................................................................................................................... 0 Suporte ao Java 5 ................................................................................................................ 0 Anotações para Pointcuts ................................................................................................ 0 Join point Match com anotações ................................................................................. 0 Recursos Avançados em Pointcuts .............................................................................. 0 Declaração de erros e warnings ................................................................................... 0 Injeção de anotações............................................................................................................ 0 Exercícios ................................................................................................................................. 0 3. Advice........................................................................... Error! Bookmark not defined. Objetivos .................................................................................................................................... 0 Tipos de Advices ................................................................................................................... 0 ThisJoinPoint........................................................................................................................ 0 Aspects........................................................................................................................................ 0 inner-type declarations ................................................................................................... 0 Exercicíos ................................................................................................................................. 0 4. Recursos Adicionais.............................................. Error! Bookmark not defined. Objetivos .................................................................................................................................... 0 AspectJ com Anotações ...................................................................................................... 0 Declare Soft ............................................................................................................................. 0 DBC ............................................................................................................................................. 0 Exercícios ................................................................................................................................. 0 HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
1. Conceitos Básicos sobre AOP
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Objetivos •
Conhecer os conceitos básicos sobre AOP/AspectJ
•
Conhecer o conceito de Concern e Crosscuting Concern
•
Conhecer a estrutura básica de um aspecto
•
Conhecer os pilares do AspectJ
•
Conhecer como funciona o mecanismo padrão de weaving do AspectJ
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Conceitos Básicos
AOP (Aspect Oriented Programing) ou em português POA (Programação Orientada a Aspectos) traz aos desenvolvedores uma separação de conceitos, especialmente conceitos Cross-Cuting, que são aspectos de um programa que afetam outros conceitos. Esses Conceitos (Crossscut) não são facilmente desacoplados do sistema. Vamos a um exemplo prático, estamos desenvolvendo um sistema para um hotel, neste sistema deve conter: check-in, check-out, sistema de tarifação e integração com sistema de aluguel de carros, estes seriam os nossos conceitos chave ou core concerms, enquanto fazer a persistência de informações e autenticação do sistema, gerenciamento de recursos (I/O) são os nossos Conceitos transversais, em inglês crosscuting comcermes. Essa divisão entre conceitos e conceitos transversais é muito importante, quando realizada, obtemos uma maior modularização e o sistema ganha e manutenibilidade. Utilizamos esse nomenclatura em engenharia de software porque os conceitos cross-cuting atravessam uma aplicação de ponta a ponta, como por exemplo gerenciamento transacional. O Time de pesquisa da Xerox, no Xerox PARC que é um centro de pesquisas, desenvolveu a primeira implementação de AOP e mais popular de todas, o AspectJ. O AspectJ está hospedado no site do projeto Eclipse e pode ser encontrado na seguinte url: http://www.eclipse.org/aspectj/. O Primeiro release do projeto foi em 2001. AspectJ é uma extensão da linguagem Java, usa todos os recursos da linguagem e acresenta seus recursos de AOP.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Concerns VS Crosscuting concerns
Muitas vezes desenvolvemos aplicações em que precisamos levar em consideração requisitos não funcionais, tais como: gerência de transação, gerência de recursos, concorrência, persistência, processamento em Batch, integração de dados, etc... Esses seriam conceitos candidatos de natureza Crosscuting concerns, muitas vezes esses conceitos estão espalhados pelos nossos componentes de negócio do sistema. Essa mistura não é benéfica, pois o desenvolvedor que está produzindo um artefato de negócio não deveria estar se preocupando com tais requisitos, essa “preocupação” pode trazer os mais diversos problemas, entre eles destacam-se: • Acoplamento com 3rd-party framewroks • Mais tempo para desenvolver um componente • Mais difícil de fazer manutenções • Mais propenso a erros • Menos coeso • Mais difícil de migrar • Menos legível Para solucionar estes problemas devemos separar ao máximo os conceitos de natureza crosscuting concerns (que atravessam o sistema) dos de natureza concerns, que seriam os de negócio. O ideal seria manter esses conceitos em extremidades opostas sempre que possível.
Figura 1.1 Concerns vs crosscuting concerns.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Concerns VS Crosscuting concerns Neste paradigma os aspectos são os crosscuting concerns e os requisitos de negócio (código java) são os concerm, nada impede de requisitos funcionais serem tratados como crosscuting concerns, mas isso não é o que ocorre na maioria dos casos. Requisitos funcionais são concerns e requisitos não funcionais são cosscuting concerns. Quando desenvolvemos uma solução em termos de software existem dois tipos de desafios envolvidos, conforme na figura a baixo.
Figura 1.2 Menor esforço A figura a cima demonstra que com aspectos é possivel reduzir o esforço de implementação de uma solução, assim obtendo mais produtividade e reduzindo o custo de desenvolvimento. Os aspectos acabam com o dilema over design vs under design, este dilema se norteia no seguinte princípio: desenvolver um wrapper em cima de algum framework como por exemplo o Log4J ou usá-lo de maneira pura. Essa questão pode criar dois resultados distintos, no primeiro over design, nós usamos o framework de maneira pura e, se precisarmos alguma funcionalidade adicional vamos ter um retrabalho. A outra auternativa under design, desde o inicio usamos um wrapper para o framework, o que pode acontecer é que não exista necessidade e por isso trabalharemos à toa. O Uso de POA elimina este problema.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Pilares do AspectJ
O AspectJ possui “classes” como na linguagem Java, porém com mais recursos ao desenvolvedor, essas “classes” são chamados de Aspects. Os aspectos tem entidades especiais que não existem nas classes Java comuns, são elas: •
Iner-type: Permite ao desenvolvedor adicionar campos, métodos ou até mesmo interfaces a classes já existentes.
•
Join points: São pontos de programas onde os aspectos e o código Java se “encontram”.
•
Pointcuts: São expressões que o programador pode formular, servem para representar qualquer ponto de execução de um programa, por exemplo, a execução de um método ou a criação de um objeto de determinado tipo.
•
Advice: Permite a execução de um “código” após a junção vinda de um pointcut. Ex.: poderíamos gerar um log toda a vez que um objeto for salvo, isso seria detectado por um pointcut e esse código de log estaria em um advice. Os tipos de adivices se resumem a : • Before: Antes da execução do método do pointcut. Ex.: antes de gravar um objeto quero logar tudo. • After: Depois da execução do método do pointcut. Ex.: depois de gravar um objeto quero logar tudo. • Around: No meio da execução de um método do pointcut. Ex.: No momento de gravar um objeto se ele for uma PessoaFisica fazer log.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Aspects Aspects são os artefatos do AspectJ para criação dos componentes de natureza crosscuting, é como se fosse uma classe Java porém, para necessidades globais. Aspectos tem a seguinte estrutura básica: package <
>; import <>; public aspect <> { // Pointcuts // Advices }
Código 1.1 Estrutura básica de um aspecto O Aspecto pode estar dentro de um package, regido pelos mesmos padrões Java, também é possível acessar qualquer recurso Java de dentro de um aspecto, este aspecto pode importar classes através da diretiva import, assim como em uma classe java. Depois vem a visibilidade do aspecto (public por exemplo) seguida por um nome, esse nome deve obedecer os padrões Java de nomes de classes. Dentro do aspecto ficam as definições, as expressões para join points, essas expressões são os pointcuts, podemos ter diversos pointcuts em um aspecto, desde que eles tenham nomes diferentes. No final ficam os advices, é possível ter multiplos advices para um mesmo aspecto, dentro
dos
advices
é
possível
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
executar
qualquer
código
Java.
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Mecanismos de Weaving
Quando trabalhamos com aspectos em AspectJ, os aspectos conhecem as classes Java, mas as classes Java não conhecem os aspectos, esta abordagem garante uma maior modularização e coesão entre artefatos de um sistema. Para que os aspectos façam as operações que desejamos, é necessário que em algum ponto do programa ocorra a junção desse aspecto com o seu código Java, esta junção se chama weaving. Existem diversas formas de weaving, dentre elas as mais comuns são: • Modificar a JVM: Seria modificado o funcionamento da JVM para reconhecer os aspectos como se fossem nativos da linguagem. • Load Time: Adicionado o weaving em tempo de carregamento, para essa implementação usa-se Reflection. • Compile time: Adiciona o weaving em tempo de compilação dos artefatos Java. Para essas técnicas existem vantagens e desvantagens, são elas: • Modificar a JVM: Vantagens: • Suporte completo ao AspectJ • Informações dos aspectos separadas • Mais performático Desvantagens: • Perda de portabilidade • Fere as especificação de bytecodes • Compilado de mudar as especificação Java
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
•
Load Time: Vantagens: •
Modifica o código somente quando é carregado, assim carregando sob-demanda.
Desvantagens:
•
•
Mais lento
•
Dificuldades de fazer otimizações
Compile time Vantagens: •
Portável, pois não modifica o bytecode
•
Mais performático, aplicação Java como qualquer outra
•
Mais fácil de implementar
Desvantagens: •
Possui mais limitações: Ligar aspectos em tempo de compilação.
•
Dificuldade em disernir código Java e código AspectJ depois do código ser gerado.
O AspectJ preferencialmente utiliza o mecanismo de compile time weaving como sua estratégia padrão de weaving. Mas essa estratégia pode ser modificada. A Figura a baixo ilustra como funciona o mecanismo de weaving baseado na estratégia de compile time para o AspectJ.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Figura 1.2 Mecanismo de Weaving na estratégia de compile time. O processo demonstrado na figura acima acontece da seguinte forma: 1. Apartir de um código Java é feita a compilação com o compilador AspectJ. 2. Apartir de um código AspectJ é feita a compilação com o compilador AspectJ. 3. Após as operações anteriores vamos ter dois bytecodes, o do código Java e o do AspectJ. 4. Com esses dois bytecodes é gerado o weaving, que é mistura dos dois códigos. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
5. Finalmente é gerado um único bytecode contendo aspectos e código Java, não quebrando a especificação bytecode Java e ao mesmo tempo atendendo os requisitos funcionais do AspectJ. No mecanismo de weaving é importante mencionar que todos os fontes Java (.class) devem estar disponiveis em tempo de compilação, caso contrário a compilação AspectJ irá falhar, isso significa que não é possível colocar advices sobre métodos nativos.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Exercícios
1) Descreva com suas palavras o conceito de AOP/AspectJ. 2) Descreva para que serve: Join point, Pointcut, Advice e Iner-type declarations. 3) Cite 3 vantagens de usar AOP 4) Descreva com suas palavras a diferença entre crosscuting e concern. 5) Descreva com suas palavras como funciona o mecanismo de weaving do AspectJ. Cite 2 vantagens.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
2. Pointcuts
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Objetivos •
Saber utilizar pointcuts com call e execution
•
Saber utilizar anotações para aspectos
•
Saber realizar expressões pointcut considerando anotações
•
Saber declarar warnigs e erros
•
Saber realizar injeção de anotações
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Pointcuts
Pointcuts são alguns join points de um programa que são capturados pelo mecanismo de AOP do AspectJ. No AspectJ existem 11 possíveis join points, veja: •
Chamada de método
•
Execução de método
•
Chamada de construtor
•
Execução de construtor
•
Getter de uma propriedade
•
Setter de uma propriedade
•
Pre-inicialização
•
Inicialização
•
Inicialização estática
•
Handler
•
Advice de execução de join points
A Captura ocorre baseada em expressões definidas pelo programador. A sintaxe de um um pointcut é a seguinte: pointcut <<nome>>(): <<expressao>;
Exemplo: package br.com.targettrust.aop.pointcuts; public aspect PointcutSample { pointcut nomePointcut(): call (void metodoX()); }
Código 2.1 – Pointcut sample No exemplo acima estamos declarando um pointcut de nome nomePointcut que irá capturar todas as chamadas ao método metodoX() de qualquer classe. Quando montamos as expressões dos pointcuts podemos utilizar operadores lógicos para juntar mais de uma expressão. O AspectJ disponibiliza os seguintes operadores lógicos: &&, || e !. Veja no exemplo a baixo como usar cada um. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
package br.com.targettrust.aop.pointcuts; public aspect PointcutLogicalOperators { pointcut operadorAnd(): call ( String br.com.targettrust.aop.java.domain.model.Pessoa.getNome() ) && call ( String br.com.targettrust.aop.java.domain.model.PessoaFisica.getNome() ); pointcut operadorOr(): call ( String br.com.targettrust.aop.java.domain.model.Pessoa.getNome() ) || call ( String br.com.targettrust.aop.java.domain.model.Pessoa.getEndereco() ); pointcut operadorNot(): call ( ! String br.com.targettrust.aop.java.domain.model.Pessoa.getNome() ); }
Código 2.2 – Pointcut operadores lógicos No exemplo acima foi demostrado o uso dos três operadores lógicos para pointcuts, é possível combinar ou usar quantas vezes forem necessárias estes operadores. Ainda é possível fazer com que um pointcut capture mais de um método e de várias classes de seu sistema, quanto a isso não existem restrições. As expressões dos pointcuts ainda suportam o wild card *. Esse wild card pode ser utilizado para os casos em que não queremos informar o nome completo de um pacote, classe ou método. Ex.: supondo uma classe de negócio que tem os métodos findCliente(), findClienteByName(), findClienteByCpf(), findClienteByTelefone() neste caso, poderíamos com uma única expressão pegar todos estes métodos, o código AspectJ ficaria assim: pointcut finds(): call (* find*(..));
Código 2.3 – Pointcut com wild cards. No exemplo acima estamos informando que queremos capturar todos os métodos find* que recebam quaisquer parâmetros e que retornem qualquer coisa. Nesse exemplo aparece a propriedade: “..” que neste contexto significa qualquer parametro ou seja, de 0..* e com qualquer tipo de dado. Outro recurso interessante é o pointcut primitivo cflow(), com ele podemos pegar a execução de outros pointcuts, por exemplo o pointcut: pointcut x(): call (* exec*(..)); se fizermos cflow(exec()) significa que enquanto o metodo exec() estiver executando alguma operação poderá ser feita. Quando ele para de executar esse ponto se torma inválido. Esse recurso é muito útil , pois podemos fazer controles enquanto algo está em execução ou enquanto algum método ainda não foi executado. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Para os 11 joinpoints, os pointcuts equivalentes são: call, execution, get, set, preinicialization, inicialization, staticinicialization, handler e adviceexecution. A figura abaixo resume o contexto de cada um destes pointcuts de forma geral.
Figura 2.1 – Contexto de pointcuts.
Call VS Execution
Para capturar a execução de um método podemos utilizar tanto o operador call como o operador execution. Porém existem algumas diferenças dos mesmos. Quando utilizamos o operador call com o operador withincode o funcionamento é diferenciado, considerando a expressão pointcut: call(void metodo()) && withincode(void metodo()). Esse pointcut só será atingido se o método estiver fazendo chamas recursivas. O operador execution já considera que o programa está em execução então a expressão: execution(void metodo()) equivale a call(void metodo()) && withincode(void metodo()). Outro aspecto importante é que o call não captura chamadas de procedências superiores para métodos não estáticos, ou seja, somente para métodos da própria classe e os métodos que estejam em uma classe pai, porém, que sejam estaticos. A regra geral é: se você deseja capturar algum trecho de código em particular para realizar algum tracing por exemplo, utilize execution. Mas se você deseja capturar um método com uma assinatura particular que normalmente é utilizado em aspectos que vão para produção, utilize call.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Suporte ao Java 5.0
A versão 1.5.X do AspectJ prove suporte completo aos recursos do Java 5.0 como: varargs, anotações, retorno co-variante, enumerations, generics e autoboxing. O AspectJ prove um set muito rico de recursos para anotações que serão bem detalhadas na sequência. Os recursos de auto-boxing são transparentes para o AspectJ, ou seja, não há diferenças em join points, pointcuts ou advices entre primitivos e wrappers.
Exemplo:
args(Integer) ou args(int) são equivalentes. Os recursos de co-variante são aplicados a expressões de pointcuts também, e isso acontece de forma natural. O Mecanismo do AspectJ já irá levar essas considerações quanto a retorno covariante em consideração. Quando utilizamos varargs podemos realizar expressões pointcuts levando em consideração a sua existência. Por exemplo: initialization(org.xyz.*.new((Foo || Goo)...)) Pegaria a criação de todos os objetos do pacote xyz que tiverem no construtor um varargs de Foo ou Goo. Atenção: Quando utilizamos varargs a syntax é <<Tipo>>..., não confunda essa syntax com os recursos do próprio AspectJ(..). O recurso .. captura quaisquer argumentos. No que diz respeito aos recursos de enumerations é exatamente igual ao Java, a mesma sintaxe e
as
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
mesmas
limitações.
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Anotações para Pointcuts
Anotações foram introduzidas no Java 5.0 e provem um mecanismo elegante para informar metadados. Uma anotação se caracteriza pela syntax: @<<nome>>. As anotações podem ser utilizadas em: classes, interfaces, construtores, métodos, atributos de classes e parâmetros. As anotações podem ser de um único valor ou de muitos valores. Quando utilizamos anotações, lidamos com políticas de retenção: •
Código Fonte: São lidas no processo de compilação, mas não são colocadas no class gerado.
•
Class gerado: É a politica de retenção padrão, as informações estão tanto em tempo de compilação quanto no class gerado.
•
Runtime: São lidas pelo compilador, vão para o class gerado e ainda podem ser obtidas em tempo de runtime.
Podemos recuperar as informações de annotations em tempo de runtime se a política de
retenção
permitir,
AnnotatedElement
e
para
isso
utilizamos
reflection,
existe
através
dos
métodos:
getAnnotation(),
uma
interface
getAnnotations(),
isAnnotationPresent(). Por padrão annotations não são herdadas no mecanismo padrão de herança do Java. Mas é possível fazer herança utilizando a annotação @Inherited. O AspectJ Prove anotações bem como alternativa a sua syntax de aspectos, existe um conunto de annotation para a utilização do AspectJ . No Java 5.0 quando usamos alguma Collection não tipada o compilador emite um warning, podemos eliminar esse warning com uma annotation, isso existe no AspectJ também, pois é possível que o compilador AspectJ não consiga estabelecer nenhum join point para seu pointcut então, para evitar warnings podemos utilizar a annotation @SuppressAjWarnings. No AspectJ Podemos colocar anotações em: aspectos, métodos, atributos, construtores, advice, iner-type declaration com aspectos. Não podemos utilizar annotation em declarações de pointcus.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Join Point match com annotations
É possivel realizar matching de join points com presença ou falta de determinada annotation. Basicamente existem duas formas sintáticas de utilizar join points com annotation, são elas: Nome qualificado: Neste caso, podemos capturar todos os elementos que contenham determinada annotation. EX: @Gravavel ou @com.targettrust.aop.Curso ou !@Gravavel Type + Pattern: Nesse estilo podemos capturar todas as annotations de determinado tipo e ainda utilizando expressões com wild cards. Ex.: @(org.target..*) ou @( Gravavel || NaoGravavel) O Mecanismo de join points com annotation é bastante fexível, abaixo temos algumas das possíveis combinações para criarmos expressões de pointcuts utilizando annotations. Os exemplos a seguir se aplicam a call() e execution().
Expressão
Exemplo de uso
(@Executavel * *)
Contém a annotation @Executavel
(!@Executavel * *)
Não contém a annotation @Executavel
(@Executavel @Runnable * * )
Que contém as annotations @Executavel e @Runnable
( @(Executavel || Runnable) * *)
Que contém a annotation @Executavel ou a
annotation @Runnable @(br.targettrust..*)
Qualquer annotation que esteja no pacote ou subpacote br.targettrust
Tabela 2.1 – Exemplos com annotation e operadores lógicos Os recursos de match de join point com annotation em AspectJ são muito maleáveis (como demostrado na tabela acima), agora será exemplificado o uso dessas annotations em atributos e construtores. A Próxima tabela exemplifica como utilizar annotation para os poitcuts com construrores baseados em annotation. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Expressão
Exemplo de uso
@Criavel new(..)
Qualquer
construtor
que
tenha
a
annotation @Criavel !@Criavel new(..)
Qualquer construtor que não tenha a
annotation @Criavel. Cuidado com a interceptação de aspectos. @Criavel new(java.util.List)
Qualquer construtor que receba um parâmetro do tipo List.
@Criavel private new(..)
Qualquer construtor privado que possua a
annotation @Criavel. Tábela 2.1 – Exemplos com anotações e operadores lógicos para construtores
Poderíamos ainda utilizar mais operadores lógicos como || ou &&, ainda seria possível elaborar expressões mais complexas, quando fazemos um pointcut para construtor utilizamos a propriedade initialization, mas podemos usar outras propriedades juntas a esta. Para fazer as expressões sobre atributos, usamos o padrão Java Bean e os métodos getters/setters. Veja abaixo um exemplo de como utilizar esse recurso com annotations.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Recursos Avançados em pointcuts
Além dos recursos já demonstrados anteriomente nesta apostila, o AspectJ possui recursos ainda mais apurados para criarmos expressões mais poderosas, dentre esses recursos contamos com: args, this, target, within, whitioncode, annotation. Todos estes recursos citados acima tem suas equivalências com a “@” na frente indicando que é o mesmo recurso porém utilizando annotations. @args/args: Este recurso faz o match apartir do tipo e da ordem dos argumentos. É baseado no tipo do objeto em tempo de runtime, o recurso @args também pode ser utilizado em conjunto com annotations. Podemos utilizar os wild cards “*” e “..”. Ex.: @args(*,Persistivel) este exemplo captura um recurso em que tenha qualquer tipo no primeiro argumento e no segundo argumento tenha uma annotations do tipo Persistível. @this/this: Este recurso faz o match apartir do objeto que foi interceptado, com isso podemos especificar sub-clausulas nas expressões de join points. Ex.: @this(Persistivel) && within(br.com) esse exemplo pega todos os objetos do pacote br.com que tenham a annotations @Persistivel. @target/target: Esse recurso faz o match apartir do objeto que é o alvo do match AOP. Quando utilizandomos target estamos nos referindo simplesmente ao alvo e @target refere-se as annotations que o alvo tem. Este alvo é o objeto que foi “capturado” pelo mecanismo AOP. Ex.: @target(Simples) captura se o target tiver a annotations simples. @within/within:Esse recurso faz o match apartir do objeto que é instanciado. Esse recurso é utilizado para fazer filtros de aspectos em determinados pacotes, e o @within é a mesma coisa, porém para annotations em pacotes ou sub-pacotes. Ex.: call (* *(..)) && within(com.br.*) essa expressão capturaria qualquer execução de método, porém que esteja no pacote com.br ou sub-pacote. @withincode/withincode: Esse recurso é muito poderoso. Ele é semelhante ao within, com a vantagem de podermos avaliar os códigos, blocos de códigos, ele é utilizado para o reforço de contrato, nos próximos capítulos será abordado com mais detalhes.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
@annotation: Esse é um recurso bastante avançado nas expressões de pointcuts do AspectJ 1.5.X, com esse recurso podemos capturar annotations que tenham uma política de retenção forte, ou seja, política de retenção em runtime. Ex: call (* * (..)) && @annotation(Forte) captura qualquer chamada de método em que o interceptado tenha a annotation @Forte e essa anotação tenha política de retenção em runtime.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Declaração de erros e warnings
É possivel gerar warnings e até mesmo erros com aspectos, isso se torna muito interessante por exemplo para evitar que desenvolvedores acessem métodos @Deprecated. Esse recurso pode ser utilizado para o reforço de contratos e até mesmo para evitar o acoplamentos de código. Quando usamos warnigs o mecanismo do AspectJ não impede a compilação, ou seja, o mecanismo de weaver acontece sem problemas, porém quando declaramos erros é como se existissem erros sintáticos no código e ele não compilasse, logo isso impossibilitaria a execução do programa. Veja no código a baixo exemplos de como utilizar os recursos do AspectJ para declaração de erros e warnings, neste mecanismo não é necessário ter um advice relacionado ao pointcut, este é um caso especial em que o pointcut fica sem um advice explícito. package br.com.targettrust.aop.pointcuts.annotation.erroswarnings; public aspect JoinPointMacthWithAnnotationErrosWarnings { declare warning : within(br.com.targettrust.aop.pointcuts.annotation.erroswarnings.java.*) && call(* faz*(..)) : "Você não deve chamar metodos com o prefixo faz*"; declare error : within(br.com.targettrust.aop.pointcuts.annotation.erroswarnings.java.*) && call(* deleteAll*(..)) : "Você não deve deletar tudo tche!!!"; }
Código 2.4 – Utilização de error e warning em pointcuts.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Injeção de Annotações
No AspectJ 1.5.X é possível adicionar annotations em tempo de runtime em objetos Java. Esse recurso é muito útil, pois com ele fica fácil de realizar tarefas dinâmicas baseadas em annotations. Esse recurso possibilita adicionar annotations em: •
Classes
•
Métodos
•
Construtores
•
Atributos
Este recurso é realizado através de expressões de pointcuts, este também é um caso especial de pointcut, porque assim como os recursos de declaração de warnings e erros não necessitam ter um advice associado, esse recurso também. Para isso utilizamos o operador declare, porém com annotations indicando o tipo de recurso que será injetado. As terminologias permitidas para estes recursos são: @type, @method, @constructor, @field. Ainda não existe suporte para injeção de annotations em pacotes. Veja no código abaixo exemplos de uso destes recursos. package br.com.targettrust.aop.pointcuts.annotation.declareann; import br.com.targettrust.aop.pointcuts.annotation.declareann.java.*; public aspect JoinPointMacthWithAnnotationDeclareAnn { declare @type : br.com.targettrust.aop.pointcuts.annotation.declareann.java..* : @Exportavel; declare @field : * br.com.targettrust.aop.pointcuts.annotation.declareann.java..*.*
: @Campo;
declare @method : public * br.com.targettrust.aop.pointcuts.annotation.declareann.java.DeclareAnnTest4.* (..) :@Metodo; declare @constructor : br.com.targettrust.aop.pointcuts.annotation.declareann.java.DeclareAnnTest3+. new(..) : @Novo; }
Código 2.5 – Exemplos de utilização de injeção de annotations
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Exercícios
1) Faça um aspecto que intercepte toda criação de objetos que o construtor receba uma String. 2) Faça um aspecto que intercepte toda execução de métodos que recebam um Map como argumento. 3) Faça um aspecto que declare erros se o desenvolvedor instanciar algum objeto do tipo ArrayList. 4) Faça um aspecto que injete annotations em objetos de pacotes dao. 5) Faça um aspecto que intercepte todas os getters que tenha a anotação @Serializavel no target.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
3. Advice
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Objetivos •
Saber utilizar os tipos de Advices do AspectJ
•
Conhecer recursos de ThisJoinPoint
•
Saber criar aspectos
•
Saber utilizar inner-type declarations
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Advices
No AspectJ 1.5.X quando criamos pointcuts ( e atingimos um ou mais join points) é para podemos aplicar algum tipo de processamento sobre os join points. Pointcuts em si não realizam nenhuma ação sobre o código Java, para realizar essa tarefa nececitamos de um advice. O AspectJ prove diversos tipos de advices, são eles: •
Before
•
Around
•
After
Quando utilizamos advices, precisamos fazer referência a um pointcut ou podemos declarar um pointcut diretamente após a declaração do advice. A primeira forma é útil quando queremos utilizar múltiplos advices e a segunda quando só temos um único advice. Veja abaixo o exemplo de uso de um simples advice. public aspect SimpleAdvice { before(int x): call (* *.*.exec*(int)) && args(x) { System.out.println("[SimpleAdvice]modificado: " + (x+1)); } }
Código 3.1 – Exemplo de um Advice simples.
No exemplo acima foi declarado um advice do tipo before(), e este advice irá interceptar todos os métodos exec* de qualquer classe, de qualquer package. Esse advice está capturando o parâmetro int do método exec*, este parâmetro é referenciado pela variável x. Esse advice não faz nada além de imprimir na tela o número do argumento, atribuindo mais um.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Tipos de Advices
Before: Esse tipo de advice é executado antes da execução do pointcut. Supondo que você declarou um pointcut que pega todas as execuções métodos que retornem um double, com o advice before você tem o controle antes da execução do método. Esse advice permite modificar os parâmetros do método, é ideal para fazer todo o tipo de inicialização. Outra boa aplicação para este advice é para validações, podemos fazer validações antes da execução de determinados métodos. Veja abaixo exemplos de uso do advice before em aspectos com AspectJ. public aspect BeforeSimple { before(): call(* *.*save(Object)) { System.out.println("Simples execucao antes do metodo."); } }
Código 3.2 – Exemplo de um Advice do tipo before.
O Advice acima captura todas as execuções do método save que recebe um Object como parâmetro. Foi utilizado pointcuts em linha por questões de facilidades. Esse advice só imprime uma mensagem na tela. Seria possível fazer validações neste advice e com isso poupar tempo dos desenvolvedores e garantir que todos os acessos ao banco sejam menos custosos. Para exemplificar isso o advice acima foi alterado, veja o resultado na figura abaixo. before(Object x): call(* *.*save(Object)) && args(x) { if (x==null) throw new RuntimeException("Não pode salvar um objeto nulo!"); }
Código 3.2 – Exemplo de um Advice do tipo before com validação.
As modificações relevantes aqui são as seguintes: *foi adicionada a expressão pointcut args que possibilida fazer referências aos argumentos dos métodos e *no advice before foi adicionada uma variável de pilha chamada x, que é a mesma do args.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
After: Este tipo de advice é executado depois da execução do pointcut. Supondo que você declarou um pointcut que pega todas as execuções métodos que retornem um double, com o advice after você tem o controle posterior à execução do método. Esse tipo de advice permite modificar o retorno de um método. É útil para aplicar filtros e adicionar informações a grafos de objetos. Este tipo de recurso pode ser utilizado para realizações de bind dos mais diversos tipos, como por exemplos de-paras. Veja abaixo exemplos de uso do advice before em aspectos com AspectJ. public aspect AfterSimple { after(): call(* *.*save(Object)){ System.out.println("Simples execucao depois do metodo."); } }
Código 3.3 – Exemplo de um Advice do tipo after.
Outra forma de usar o advice after é com o retituring que permite capturar o retorno da execução de algum pointcut. Esse recurso pode ser usado de forma opcional. No exemplo abaixo mostra como utilizar o recurso. after() returning(Object o): call(public Object *.*.find()){ String x = (String)o; x += "123"; System.out.println("retorno: " + x); }
Código 3.4 – Exemplo de um Advice do tipo after com returning.
Este advice pega o retorno do método find, sendo que esse método retorna um objeto. No advice foi feito um cast para String e adicionado o sufixo 123 na String original e depois é impresso na tela. O Advice after ainda possui o recurso de throwing que serve para capturarmos após o levantamento de Exception. Veja abaixo um exemplo de uso desse recurso.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
O Advice do tipo after ainda possui mais uma forma, a throwing, com isso podemos realizar operações após um método levantar uma determinada exception por exemplo. Esse recurso faz com que o advice seja executado apenas se a Exception corretamente definida na expressão pointcut for lançada. Veja a baixo um exemplo prático de como usar o after throwing. after() throwing(Exception e): call(public void *.*.delete()) { System.out.println("Erro! Mensagem: " + e.getMessage()); }
Código 3.5 – Exemplo de um Advice do tipo after com throwing.
No advice after acima, dentro da palavra reservada throwing, informamos a Exception que desejamos capturar, nesse exemplo foi utilizada uma exception genérica mas poderíamos
informar
uma
exception
específica,
como
por
exemplo
FileNotFoundException. Este recurso é muito bom para aplicar logs e todo o tipo de controles pós erro. Outra aplicação seria na tolerância a falha, em um sistema assíncrono poderíamos disparar um segundo processo caso determinado erro ocorra.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Around: Com certeza este é o tipo de advice mais poderoso e mais utilizado. Com esse advice podemos interferir na execução do método de forma que possamos: •
Impedir a execução
•
Modificar os parâmetros
•
Modificar o retorno
•
Levantar um Exception
•
Engolir um Exception
Esse advice abre uma imensa gama de possibilidades. Quando utilizamos around é necessário especificar uma sintaxe um pouco diferente dos outros advices, dentre as diferenças existe o proceed(). Este método faz com que a execução do método prossiga. Para o mesmo ocorrer é necessário informar os parâmetros do método, podemos repassar os parâmetros originais, novos ou modificados. int around(): call(public int *.*.soma(int,int)){ System.out.println("Around advice modificando valores constante 1"); return 1; }
Código 3.6 – Exemplo de um Advice do tipo around.
No exemplo acima o advice around está interceptando o método soma de qualquer classe, está imprimindo uma mensagem e retornando 1. Como o advice around está definido como int isso torna obrigatório o retorno de um inteiro. Esse retorno está hardcoded, mas poderia ser dinâmico.
Veja no exemplo
abaixo como podemos fazer isso utilizando o proceed(). int around(int x,int y): call(public int *.*.soma2(int,int)) && args(x,y){ System.out.println("Around advice modificando valores dinamicos"); return proceed(x,y); }
Código 3.6 – Exemplo de um Advice do tipo around com proceed().
Neste exemplo foi utilizado o recurso args para recuperar os argumentos do método soma2 e esse argumentos x,y foram referenciados dentro do advice around. No final é executado o proceed que executa o método real com os parâmetros. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
OBS: Quando utilizamos around como advice é de extrema importância utilizar o proceed(), mesmo quando o método é void. Se o proceed() não for executado dentro do advice around o método original não será executado. Ás vezes você pode querer fazer como forma de alguma política de segurança, mas lembre-se: o método não será executado. Quando declaramos exceptions checadas em advices elas devem ser declaradas com a cláusula throws, e a mesma deve ser compatível com a do método original, caso ocorra de modo contrário o compilador irá apresentar um erro. Sobre a precedência de advices: Quando existem dois advices em dois aspectos disitintos é impossível determinar qual irá executar primeiro. Quando existe um advice que está em um aspecto abstrato e outro em um aspecto concreto que extende o do abstrato, o abstrato tem precedência. E quanto a dois advices declarados no mesmo aspecto, o que for declarado primeiro terá precedência sobre os outros. Estas informações são importantes se você deseja aplicar algum mecanismo de proxy como segurança, transação, autenticação, log. Pode ser necessário estabelecer uma precedência entre os aspectos que aplicam os cross cuting concerns.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
ThisJoinPoint
AspectJ prove uma variável de referência especial chamada de thisJoinPoint. Essa variável de referência contém informações sobre o joint point corrente para que possamos utilizar estas informações no advice. O recurso thisJoinPoint só pode ser utilizado no contexto de um advice, existe um objeto AspectJ que ele representa que é org.aspectj.lang.JoinPoint. Supondo que tenhamos a seguinte classe Java: package br.com.targettrust.aop.advice.thisJoinPoint.java; public class ThisJoinPointTest { public static void execute(){}; public static void main(String[] args) { execute(); } }
Código 3.7 – Exemplo de uso de thisJoinPoint. O método execute não faz nada, mas está sendo invocado no método main. package br.com.targettrust.aop.advice.thisJoinPoint; public aspect ThisJoinPoint { void around(): call(void *.*.execute()) && within(br.com.targettrust.aop.advice.thisJoinPoint.java.*){ System.out.println("Executando: " + thisJoinPoint.toString()); } }
Código 3.8 – Exemplo de uso de thisJoinPoint em aspecto. O aspecto acima apenas imprime uma mensagem usando algumas informações que existem no join point corrente. Veja o resultado da execução deste programa abaixo. Executando: call(void br.com.targettrust.aop.advice.thisJoinPoint.java.ThisJoinPointTest.execute())
Código 3.9 – Resultado da execução.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Como demostra o código acima, o uso de thisJoinPoint leva a um objeto JoinPoint do AspectJ, e foi invocado o metodo toString() que retorna uma representação em forma de String do joinpoint relacionado. Os principais métodos de thisJoinPoint() são: Método
Descrição
getArgs()
Retorna os argumentos do método
getSignature()
Retorna a assinatura do método
getSourceLocation()
Fonte e linha do código Java
getClass()
Retorna a classe de implementação do JoinPoint
getKind()
Tipo de join point. Ex.: method-call
getTarget()
Retorna o objeto (Java) em execução
getStaticPart()
É um helper do join point que contém as informações que podem ser acessadas de forma estática.
getThis()
Semelhante ao target, porém sempre irá retornar o objeto que estiver relacionado ao this() de expressão pointcut.
Quando estamos em um advice do tipo after ou before e existe uma expressão call(), é possível acessar informações do joint point passado quando ele existe, para isso usamos a variável thisEnclosingJoinPointStaticPart.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Aspects
Aspectos são tipos de dados em AspectJ semelhantes a uma classe Java, os aspectos são os meios que possibilitam a expressão de um crosscuting concern. É dentro dos Aspectos que são declaradas as expressões pointcuts e os advices. A declaração de aspectos é semelhante a declaração de uma classe Java. Quando estamos declarando um aspecto podemos: •
Declarar métodos e variáveis Java
•
Aspectos alinhados precisam ser estáticos
•
Aspectos não são instanciados
Quanto a característica de os aspectos não serem instanciados com a palavra reservada new, os mesmos não são clonados ou serializados diretamente. Aspectos podem ter um construtor desde que o mesmo não tenha argumentos e não retorne exceptions checadas. Os aspectos podem estender classes e até mesmo implementar interfaces. As classes Java não podem estender aspectos, isso gera um erro de compilação. Aspectos podem extender outros aspectos, desde que abstratos, se um aspecto tenta estender outro aspecto que não é abstrato causa um erro de compilação. Por default os aspectos são singletons, significa que a mesma instância do aspecto será para toda execução de um programa Java. Podemos recuperar a instância de um aspecto com uma classe utilitária do AspectJ, a org.aspectj.lang.Aspects que tem os seguintes metodos: •
aspectOf(Class c): Que recebe a class do aspecto e retorna a intância do mesmo aspecto. Pode ser chamado por qualquer aspecto.
•
hasAspect(Class c): Retorna true ou false se a classe for um aspecto.
Obs.: A Classe utilitária org.aspectj.lang.Aspects não pode ser utilizada em uma classe Java, pois isso quebra o conceito básico de AOP, os aspectos podem ver as classes Java, entretanto as classes Java não vêem os aspectos. Se você fizer isso irá receber um erro de compilação.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Veja abaixo um exemplo de como podemos utilizar aspectos abstratos e extensão de aspectos com os recursos da classe utilitária Aspects.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
package br.com.targettrust.aop.aspect.java; class A{ public void func(){} } class B{ public void func(){} } public class SingletonTeste { public static void main(String[] args) { A a = new A(); B b = new B(); a.func(); b.func(); } }
Código 3.10 – Classe java de testes.
Supondo que temos as três classes acima, a classe A e B com o método func() e uma classe main com a instanciação e invocação dos métodos func() de A e B. Agora se quiséssemos contrar quantas vezes o método func() foi chamado. poderíamos fazer um aspecto conforme este abaixo: package br.com.targettrust.aop.aspect; public abstract aspect PaiBurro { protected String nome = "Aspecto Contador"; }
Código 3.11 – Exemplo de um aspecto abstrato. package br.com.targettrust.aop.aspect; import org.aspectj.lang.Aspects; public aspect Singleton extends PaiBurro{ private int cont = 0; after(): call(* *.*.func()){ cont++; Singleton o = (Singleton)Aspects.aspectOf(Singleton.class); System.out.println("Metodo:" + thisJoinPoint.getSignature().getName() + " invocado: " + cont + " vezes! Monitor: " + o.nome); } }
Código 3.12 – Exemplo de um usando a classe utilitária Aspects
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Obs.: Se múltiplos classloaders carregarem múltiplas classes, e essas classes tenham join points com aspectos, esses aspectos serão instânciados uma vez a cada classloader. Como mencionado antes, os aspectos são singletons, porém por classloaders. Um advice só pode rodar no contexto de um aspecto, se o mesmo não tiver sido instânciado ele não pode rodar, se por algum motivo um advice for executado antes da criação do aspecto, como por exemplo fazer um before advice de um execução new(), isso
fará
com
que
o
AspectJ
levante
um
exception:
org.aspectj.lang.NoAspectBoundException. Por default aspectos tem as mesmas regras de acesso e privilégios que o Java tem, mas podemos modificar essas políticas tornando o aspecto privilegiado. Quando um aspecto é privilegiado, o mesmo pode acessar variáveis protected e até mesmo variáveis private. Porém esses recursos só são válidos para innertype declarations feitas pelo mesmo aspecto ou por outros.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Inner-Type Declarations
Recurso do AspectJ que permite adicionar membros nas classes de forma dinâmica. Com este recuroso podemos adicionar atributos a um classe Java e utilizar essa informação para algum processamento em algum advice de um aspecto. Não é difícil adicionar métodos a classes Java com os recursos de inner-type declarations do AspectJ, podemos inclusive fazer com que determinada classe implemente um set de interfaces. Como mencionado anteriormente, é possivel modificar até mesmo as regras de acesso do Java, assim um aspecto privilegiado pode acessar métodos proteced e até mesmo private. Para adicionar uma classe ou interface na hierarquia de uma classe em um aspecto podemos usar o recurso declare parents. O código abaixo mostra como adicionar a Classe br.com.A como classe pai da classe br.com.B. declare parents: br.com.B extends br.com.A;
Código 3.13 – Exemplo de adição de classes com inner-type. Poderíamos adicionar interfaces também, e isso podemos fazer quantas vezes quizermos, porém é válido lembrar que quando fazemos isso somos obrigados a implementar todos os métodos definidos na interface. declare parents: br.com.B implements br.com.A;
Código 3.14 – Exemplo de adição de classes com inner-type. No exemplo acima foi feito que a classe br.com.B implementase a interface br.com.A, quando fazemos isso essas informações podem ser acessadas até mesmo por uma classe Java através de cast para a interface ou com o uso de Reflection. Para adicionar atributos a uma classe Java podemos fazer conforme o exemplo abaixo: private List Casa.portas = new ArrayList();
Código 3.15 – Exemplo de adição de atributo em classes com inner-type.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
No exemplo acima está sendo adicionda uma List no objeto casa. Perceba que o atributo está sendo adicionado de forma privada, isso significa que não poderá ser acessada de fora da classe a não ser que o aspecto seja privilegiado.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Para adicionar métodos a uma classe ( Isso é necessário quando implementamos uma interface via aspectos) podemos fazer conforme o exemplo abaixo. public void Casa.pintar(Cor c){ System.out.println("Pintando a casa de cor:" + c); }
Código 3.16 – Exemplo de adição de metodo em classes com inner-type. No código acima foi adicionado o método pintar ao objeto Casa, esse método tem como parâmetro um objeto Cor, esse método pode ser acessível normalmente se ele estiver em uma interface ou via Reflection. Dentro de um advice ou de um outro aspecto isto pode ser acessado de forma natural pois o método será público. Outro recurso que podemos utilizar é a adição de contrutores a classes Java através de inner-type declarations, confira o exemplo abaixo. public Casa.new(String rua) { super(); System.out.println(rua); }
Código 3.17 – Exemplo de adição de construtor em classes com inner-type. No exemplo acima foi adicionado um construtor ao objeto Casa, esse objeto agora tem um construtor que recebe um String contendo a rua. A chamada super() é opcional, mas o compilador AspectJ irá lançar um warning se você não a colocar. Por questões de boas práticas de programação recomenda-se utilizar. Para um exemplo mais completo com inner-type declarations, consulte o projeto do eclipse com fontes que acompanha essa apostila, lá você encontrará um exemplo de implementação do pattern observer com aspectos utilizando muito os recursos de inner-type com declare parents também. Você encontra os fontes em dois pacotes que são: br.com.targettrust.aop.innertype e br.com.targettrust.aop.innertype.java.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Exercícios
1) Faça um Aspecto utilizando o advice do tipo before() log em um arquivo texto todas as chamadas de métodos da classe Sistema. Essa classe deve ter 5 métodos: ligar(), parar(), desligar(), acelerar() e explodir(), crie a classe e forneça qualquer implementação, após isso chame algumas vezes esses métodos. 2) Aproveite o exercicio anterior e mude o advice before para o advice after e faça o método desligar(String motivo) e log isso também. 3) Faça um advice around que não execute o método ligar se o dia de hoje for par, e além disso levante um exception do tipo RuntimeExecption(“Hoje o sistema está desligado!”). 4) Crie a interface Contador com o método int contar(int i) e int showTotalCount(). Faça via inner-type declaration com que a classe sistema tenha um contador com todas as chamadas aos métodos acelerar() e parar(). Mostre o resultado em uma classe main, use cast ou reflection.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
4. Recursos Adicionais
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Objetivos
•
Saber utilizar AspectJ com annotations.
•
Saber utilizar o recurso de declare soft.
•
Conhecer o conceito DBC.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
AspectJ com Annotations
A versão 1.5.X do AspectJ prove um mecanismo no estilo de anotações do Java 5.0. O AspectJ prove um conjunto de anotações que possibilita o desenvolvimento neste estilo, porém o efeito é o mesmo que no desenvolvimento utilizando a sintaxe AspectJ. É possível combinar os dois estilos de desenvolvimento em uma mesma aplicação, podemos perfeitamente mixar os estilos até no mesmo fonte, mas isso não é recomendado por questões de boas práticas. Os
recursos
de
anotações
disponíveis
no
AspectJ
1.5.X
estão
no
pacote
org.aspectj.lang.annotation, lá podemos destacar a anotação @Aspect, ela define que uma classe é um aspecto para o AspectJ. Um ponto importante que deve ser lembrado quando optamos por uma abordagem dirigida a anotações, é que quando utilizamos aspectos com anotações não é possivel declarar aspectos privilegiados. Podemos utilizar pointcuts e advices através do set de anotações: @Pointcut, @Before, @After, @AfterReturning, @AfterThrowing e @Around. Quando utilizamos o @Pointcut para declarar o pointcut existem algumas regras, tais como: o método deve retornar void, não deve ter nada no seu corpo (exeto o caso if que será abordado mais tarde). Para declarar um pointcut abstrato basta fazer com que o método seja abstrato. Ao fazer desta maneira pode parecer um pouco estranha a forma de uso, e é mesmo bastante incomun. O que se pode fazer é utilizar expressões pointcuts direto em anotações advice, isso faz com que o código fique mais natural. Se você utilizar algum recurso do tipo: args(), target(), this(), @args(), @this(), @annotation, o parâmetro em questão deverá aparcer na assinatura do método que contém a annotation @Pointcut. Obs.: No escopo de desenvolvimento AspectJ com anotações os imports não surtem efeito para as anotações, então se você que usar um List, deve colocar o nome completo da classe. Ex.: java.util.List ao invés de List. Para o uso do recurso if() o método deve ser public static boolean como no exemplo abaixo.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
@Pointcut("call(* *.*(int)) && args(i) && if()") public static boolean chamadaIf(int i) { return i > 0; }
Código 4.1 – Exemplo de anotações com if() e com annotations O exemplo acima define um pointcut que captura todas as chamadas de métodos que recebam um inteiro e este inteiro seja maior que zero. Esse código acima tem equivalência ao seguinte código AspectJ: pointcut chamadaIf(int i) : call(* *.*(int)) && args(i) && if(i > 0);
Código 4.2 – Exemplo de anotações com if() na sintaxe AspectJ Para capturar o joint point corrente para algum processamento, basta declarar o org.aspectj.lang.JoinPoint no Pointcut e depois no Advice e pronto! O mecanismo de annotations irá prover a instância desse objeto. Para utilizarmos as anotações destinadas a advices o método Java deve retornar void e ser público, porém no caso do advice around, o advice deve retornar o tipo de dado conforme a especificação do pointcut do advice around. No caso dos advices @AfterReturning e @AfterThrowing, eles não expõe o método em questão anotado ao retorno ou a execption levantada, conforme mostra o exemplo abaixo. @AfterReturning("criticalOperation()") public void phew() { System.out.println("phew"); } @AfterReturning(pointcut="call(Foo+.new(..))",returning="f") public void itsAFoo(Foo f) { System.out.println("It's a Foo: " + f); }
Código 4.3 – Exemplo de anotações advice afterReturning. No exemplo acima estamos capturando todas as instâncias das classes Foo ou filhas dele e pegando o retorno em f que é utilizando no advice. @AfterThrowing funciona da mesma forma porém ao invés do atributo returning ele possui
o
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
atributo
throwing.
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Com o advice do tipo @Around existe o problema do proceed() que não pode ser chamado no meio do código Java, se não você terá um erro de compilação, para manter um bom design e a compatibilidade de compilação do mecanismo de annotações
do
Java 5.0 devemos utilziar a interface org.aspectj.lang.ProceedingJoinPoint que será um dos parâmetros do método com a anotação @Around. @Around("call(* *.*.now(..))") public String getData(ProceedingJoinPoint pjp){ try { System.out.println(pjp.getSignature()); return (String)pjp.proceed(); }catch (Throwable e) { return null; } }
Código 4.5 – Exemplo de anotações advice around com uso de proceed. No exemplo acima fica bem claro que utilizar esse recurso é simples, e na instância de ProceedingJoinPoint ainda contamos com recursos do JoinPoint, como por exemplo a assinatura do pointcut().
Inner-type declarations
Quando estamos desenvolvendo voltado para anotações também podemos utilizar os recursos de inner-type declarations do AspectJ. Para respeitar os padrões do Java 5.0, quando usamos inner-type declarations através de anotações não temos disponíveis os recursos de adição de campos e construtores. Isso ocorre porque o compilador javac não tem os recursos que o compilador AspectJ possui. Somente os recursos de adição de interfaces estão disponíveis, com uma sutil diferença é possivel utilizar esses recursos. Veja o exemplo abaixo. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Considere a seguinte classe Java. package br.com.targettrust.aop.annotation.innertype.clazz; public class SimpleCalc { public public public public
int int int int
soma(int a,int b) sub(int a,int b) multi(int a,int b) div(int a,int b)
{ { { {
return return return return
a+b; a-b; a*b; a/b;
} } } }
}
Código 4.6 – Classe Java para o exemplo de inner-type com anotações. Como você pode perceber é uma classe Java comum. É uma calculadora muito simples com apenas as operações básicas de soma, subtração, divisão e multiplicação. Para esse exemplo será adicionada a operação de potenciação a essa calculadora através do recurso de inner-type com anotações. Só podemos utilizar esse recurso associado a uma interface. package br.com.targettrust.aop.annotation.innertype; public interface Potencia { public int pow(int num); }
Código 4.7 – Interface de Potencia. A Interface acima define como a operação de potência deve ser. Agora vamos a implementação padrão dessa operação com o código abaixo. package br.com.targettrust.aop.annotation.innertype; public class PotenciaImpl implements Potencia{ public PotenciaImpl() { } public int pow(int num) { return num*num; } }
Código 4.8 – Implementação padrão da interface Potencia. Essa é uma implementação simples. Apenas é feita a multiplicação do número pelo proprio número e retornado isso como resultado da operação de potenciação. Veja no Aspecto seguinte como fazer a classe SimpleCacl ter os recursos da Potencia.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
package br.com.targettrust.aop.annotation.innertype; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; @Aspect public class AnnotationInnerTypeAspect { @DeclareParents( value="br.com.targettrust.aop.annotation.innertype.clazz.*", defaultImpl=PotenciaImpl.class) public Potencia implementadores; }
Código 4.9 – Aspecto com anotações que utiliza inner-type declarations. O
Aspecto
a
cima
faz
a
grande
jogada.
Através
da
anotação
org.aspectj.lang.annotation.DeclareParents vide @DeclareParents que é feito uso de inner-type. A anotação @DeclareParents tem duas propriedades value e defaultImpl. Sendo que a propriedade value serve para informar que classe ou conjunto de classes vai ganhar a nova interface, a propropriedade defaultImpl é opicional, mas sem isso a classe que recebe a interface (nesse exemplo SimpleCalc) terá de prover todos os métodos que a interface necessita. Veja que essa anotação só pode ser aplicada a tipos de dados que são interfaces, ou seja, nesse exemplo a interface Potencia está sendo dada a todas as classes do pacote br.com.targettrust.aop.annotation.innertype.clazz.*. Para testar esse recurso observe a seguinte classe Java. package br.com.targettrust.aop.annotation.innertype.java; import br.com.targettrust.aop.annotation.innertype.Potencia; import br.com.targettrust.aop.annotation.innertype.clazz.SimpleCalc; public class AnnotationInnerTypeAspectTest { @SuppressWarnings("unchecked") public static void main(String[] args) { SimpleCalc sc = new SimpleCalc(); Class[] ints = SimpleCalc.class.getInterfaces(); for(Class c: ints){ System.out.println("Implementa: " + c); } System.out.println("Potencia de 5 = " + ((Potencia)sc).pow(5)); } }
Código 4.10 – Classe de teste para inner-type declarations com anotações. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Ao rodar a classe do teste acima você verá um resultado semelhante a este: Implementa: interface br.com.targettrust.aop.annotation.innertype.Potencia Potencia de 5 = 25
Código 4.11 – Resultado da execução da classe AnnotationInnerTypeAspectTest Como você pode perceber a classe de fato implementa a interface que injetamos via AspectJ, e foi feito o cast de maneira natual para a interface Potencia. Após o cast foi invocado o método pow(5) e obtivemos o resultado correto da execução.
Declare warnings e errors
Outro recurso disponível no desenvolvimento de aspectos baseados em anotações é o recurso de geração de warnings e erros. Para
declarar
um
warning
basta
utilizar
a
anotação
org.aspectj.lang.annotation.DeclareWarning vide @DeclareWarning. Veja no exemplo abaixo como utilizá-la. @DeclareWarning("call(java.util.Date.new(..))") static final String message = "Você não deve utilizar java.util.Date. Utilize Joda-Time!";
Código 4.12 – Exemplo de uso de declare warning com anotações. Nessa anotação você deve informar uma expressão pointcut que será responsável por determinar quais serão os alvos de seu warning. Essa anotação deve se utilizada em cima de um atributo do tipo String que deve ser obrigatoriamente final, por questões de boas praticas você pode colocar static também. Para declarar um error basta utilizar a anotação org.aspectj.lang.annotation.DeclareError vide @DeclareError. Veja no exemplo abaixo como utilizá-la. @DeclareError("call(public void *.apagaGeral()) ") static final String error = "Isso é um erro não apague nada!";
Código 4.13 – Exemplo de uso de declare error com anotações. O Recurso de declarar erro é muito semelhante ao recurso de declarar um warning. Também devemos informar uma expressão pointcut que será responsável por HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
determinar quais classes ficaram com erros. Claro que também é necessário um String do tipo final para ser a mensagem de erro.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Declare Soft
Esse recurso foi introduzido apartir do AspectJ 1.5.X. É um recurso muito importante com ele podemos fazer com que as Exceptions do Java sejam encapsuladas em uma Exception do
AspectJ que é do tipo unchecked e por consequência estende
RuntimeException. Se a exceção que for utilizada para o soft for uma Exception que estende RuntimeException você receberá um warning e o soft não irá ocorrer. A Exception do AspectJ que vai ser a encapsuladora de sua exeção será a org.aspectj.lang.SoftException. Esse recurso é útil para tratar os erros provocados porventura por aspectos. Veja como utilizar o recurso no exemplo abaixo: package br.com.targettrust.aop.declaresoft; public class MinhaExcpetionChata extends Exception { private static final long serialVersionUID = 1L; public MinhaExcpetionChata(String msg) { super(msg); } public MinhaExcpetionChata(String msg,Throwable rootCause) { super(msg,rootCause); } }
Código 4.14 – Exemplo de uso de declare soft. Esta é apenas uma Exception checada chamada de MinhaExceptionChata. Veja como fazer o soft dela no código AspectJ abaixo: package br.com.targettrust.aop.declaresoft; public aspect DeclareSoft { declare soft : MinhaExcpetionChata : execution(* *(..)); }
Código 4.15 – Aspecto que faz o soft. No aspecto acima foi informado em qual Exception deveria ser feito o soft e qual expressão pointcut deveria ser aplicado. Assim podemos limitar o soft somente para alguns métodos. Para testar o recurso observe a classe Java de testes abaixo:
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
package br.com.targettrust.aop.declaresoft.java; import org.aspectj.lang.SoftException; import br.com.targettrust.aop.declaresoft.MinhaExcpetionChata; public class DeclareSoftTest { public void fazAlgo() throws Exception { throw new MinhaExcpetionChata("Exception chata mesmo"); } public static void main(String[] args) { try { DeclareSoftTest dst = new DeclareSoftTest(); dst.fazAlgo(); } catch (SoftException se) { System.out.println(" 1 - SoftExcetion: " + se.getWrappedThrowable()); } catch (Exception e) { System.out.println(" 2 - Exception: " + e); } } }
Código 4.16 – Classe de testes para declare soft. Essa classe de testes chama o metodo fazAlgo() que retorna um Exception do tipo MinhaExceptionChata essa exception vai sofrer o soft. Podemos observar que isso ocorre pelo seguinte bloco de try/cacth neste bloco está sendo tratada uma exception do Java e a SoftException do AspectJ. Veja o resultado da execução desse código abaixo. 1 - SoftExcetion: br.com.targettrust.aop.declaresoft.MinhaExcpetionChata: Exception chata mesmo
Código 4.16 – Resultado da execução da classe DeclareSodtTest.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
DBC: Design By Contract
O AspectJ possibilita a aplicação dos conceitos de DBC. Design By Contract é um conceito que se norteia basicamente em pré condições, pós condições e invariantes. O seu propósito é garantir um contrato mais consistente do que nós temos por exemplo com uma interface Java. Considere a seguinte interface: package br.com.targettrust.aop.dbc; import java.math.BigDecimal; public interface ContaCorrente { public void debitar(BigDecimal valor); public void creditar(BigDecimal valor); public BigDecimal consultaSaldo(); }
Código 4.17 – Interface de conta corrente. Em Java, interfaces são conhecidas como contratos, porém se analizarmos de maneira mais crítica vamos ver que é um contrato muito fraco. Nada impede que a implementação de ContaCorrente faça um débito em uma conta que não tenha saldo ou fazer um saque em uma conta que não tem fundos. Podemos resolver estes problemas em tempo de design? Sim, com DBC podemos fazer isto. Para isto, usaremos os conceitos de pré-condições, pós-condições e invariantes. Pré-Condições: Condições que devem ser atendidas antes da execução do método em questão. Ex: Não queremos que o método debitar receba um valor negativo, então podemos dizer que uma pré-condição é que o argumento valor não pode ser menor que 1. Pós-Condições: Condições que devem ser aceitas após a execução do método em questão. Ex.: Não queremos que após um saque a conta fique no negativo, ou seja, o usuário do banco não pode sacar mais do que ele tem na conta. Então podemos determinar uma pós-condição, que diz que após a execução do método debitar() seja executado o método consultaSaldo() e o mesmo não pode ter um retorno menor que zero. Invariantes: Invariantes são como constantes. São operações ou variáveis que desejamos que sempre tenham determinado valor. Ex.: Poderíamos dizer que uma invariante é que o saldo da conta nunca pode ficar menos que 100 reais.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
DBC é um conceito em tem diversas implementações em muitas linguagens como C, Java, .NET , Ruby, etc. Podemos fazer uso fruto dos conceitos de DBC com o próprio AspectJ, porém não temos recursos prontos na linguagem para isso. O recomendo é um framework de DBC para Java, existem muitos dentre eles o JContract, C4J, Contract4J que utiliza o AspectJ como base. Veja um exemplo de implementação de DBC utilizando AspectJ puro. Considere a interface ContaCorrente mostrada acima. Considere as seguintes regras: Pré-Condições: • O método debitar não pode receber um argumento menor que 1. • O método debitar não pode receber um argumento maior que 1.000 Pós-Condições: • Após o saque a conta deve ter no mínimo 5 reais. Invariantes: • A Conta nunca pode estar no negativo. Para atender esse contrato estabelecido através das premissas do DBC veja a classe Java abaixo. package br.com.targettrust.aop.dbc; import java.math.BigDecimal; public class ContaCorrenteImpl implements ContaCorrente { private BigDecimal grana = new BigDecimal(5); public BigDecimal consultaSaldo() { return grana; } public void creditar(BigDecimal valor) { grana = grana.add(valor); } public BigDecimal debitar(BigDecimal valor) { grana = grana.subtract(valor); return grana; } }
Código 4.18 – Classe Java para implementação padrão da conta corrente.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Pela implementação da classe Java podemos ver que não foi implementado nenhum tipo de validação para atender o contrato DBC que foi estipulado previamente. Provavelmente se esta classe fosse executada do jeito que ela se encontra, teríamos sérios problemas. Agora vamos ver o aspecto que terá a implementação DBC.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
package br.com.targettrust.aop.dbc; import java.math.BigDecimal; public aspect DBCAspect { private pointcut debitarPointcut(BigDecimal b): execution(public BigDecimal *.debitar(BigDecimal)) && args(b) && within(br.com.targettrust.aop.dbc.*); before(BigDecimal b): debitarPointcut(b){ if (b.doubleValue()<1) throw new RuntimeException("O Metodo ContaCorrente.debitar(BigDecimal) " + " não pode receber um valor menor que 1! Valor: " + b.doubleValue()); } before(BigDecimal b): debitarPointcut(b){ if (b.doubleValue()>1000.0) throw new RuntimeException("O Metodo ContaCorrente.debitar(BigDecimal) " + "não pode receber um valor maior que 1.000! Valor: " + b.doubleValue()); } after(ContaCorrente cc): execution(public BigDecimal *.debitar(BigDecimal)) && target(cc) && within(br.com.targettrust.aop.dbc.*) { BigDecimal saldo = cc.consultaSaldo(); if (cc.consultaSaldo().doubleValue()<=0){ cc.creditar(new BigDecimal(5d).subtract(saldo)); throw new RuntimeException("Erro a contacorrente não pode ter saldo" +"negativo! Valor: " + saldo.doubleValue()); } if (cc.consultaSaldo().doubleValue()<=4){ cc.creditar(new BigDecimal(5d).subtract(saldo)); throw new RuntimeException("Erro a contacorrente não pode ter saldo" + "menor que 5 reais! Valor: " + saldo.doubleValue()); } } }
Código 4.19 – Aspecto de uma implementação DBC. Nesta implementação não há nehum recurso que não tenha sido discutido nesta apostila, ela utiliza os recursos que você já deve estar familiarizado agora. Porém, aqui estão inseridos os conceitos de DBC que expressam pelas pré-condições, póscondições e invariantes. HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Veja um código Java para testar esses recursos em ação. package br.com.targettrust.aop.dbc.java; import java.math.BigDecimal; import br.com.targettrust.aop.dbc.ContaCorrenteImpl; import br.com.targettrust.aop.dbc.ContaCorrente; public class DBCTest { public static void main(String[] args) { ContaCorrente cc = new ContaCorrenteImpl(); try{ cc.debitar(new BigDecimal("-1")); }catch(Exception e){ System.out.println(e.getMessage()); } try{ cc.debitar(new BigDecimal("1001")); }catch(Exception e){ System.out.println(e.getMessage()); } try{ cc.debitar(new BigDecimal("2")); }catch(Exception e){ System.out.println(e.getMessage()); System.out.println("Saldo atual: " + cc.consultaSaldo()); } try{ cc.debitar(new BigDecimal("200")); }catch(Exception e){ System.out.println(e.getMessage()); System.out.println("Saldo atual: " + cc.consultaSaldo()); } } }
Código 4.20 – Classe Java para testes. Nessa classe foi forçado todos os tipos de situações que iriam estourar algum tipo de erro. Ao executar essa classe nós teremos o seguinte resultado.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
O Metodo ContaCorrente.debitar(BigDecimal) não pode receber um valor menor que 1! Valor: -1.0 O Metodo ContaCorrente.debitar(BigDecimal) não pode receber um valor maior que 1.000! Valor: 1001.0 Erro a conta corrente não pode ter saldo menor que 5 reais! Valor: 3.0 Saldo atual: 5 Erro a conta corrente não pode ter saldo negativo! Valor: -195.0 Saldo atual: 5
Código 4.21 – Resultado da execução de um aspecto estilo DBC. O Resultado comprova o esperado, conseguimos aplicar de fato uma consistência de contrato muito superior a que o mecanismo de interfaces do Java nos prove.
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Exercícios
1) Faça um aspecto utilizando anotações que faça tracing. Este aspecto deve mostrar todos os parâmetros do método e o seu retorno também. Chame o método execute (String proc, Object inst) várias vezes em uma classe de testes. 2) Declare um erro utilizando anotações para quando for utilizando a classe java.util.HashMap() em uma classe TesteMapEx02 com os métodos usaMap() e testaMap(). 3) Baseado no exercicio anterior, faça o mesmo, só que agora gere um warning, utilizando anotações também. 4) Utilizando os conceitos de DBC faça um aspecto que valide as seguintes premissas: 1 Pré condições: 1. O hotel não aceita hospedes de cabelo verde. 2. O hotel não aceita chekin antes das 10:00hs. 2 Pós condições: 1. Ao sair do hotel deve-se pagar a conta. 2. Ao sair do hotel deve-se deixar 20% de gorjeta. 3 Invariantes: 1. Para alugar o quarto a pessoa deve ter, no mínimo R$ 500,00. Para esse execício implemente a interface Hotel que segue: Package br.com.targettrust.aop.advice.after.java; import java.math.BigDecimal; public interface Hotel { public void checkIn(String corCabelo, int horaEntrada, BigDecimal dinheiroQueVoceTem); public BigDecimal getTotalConta(); public void checkOut(BigDecimal vindeDaPropina); }
Código 4.22 – Interface para o exercicio 4
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
Espaço para Anotações
HTTP://DIEGO-PACHECO.BLOGSPOT.COM
AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos
HTTP://DIEGO-PACHECO.BLOGSPOT.COM