apostila-aspectj-1.5.4 - diego pacheco

69
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 Diego Pacheco Dezembro/2007

Upload: diego-pacheco

Post on 10-Jun-2015

3.567 views

Category:

Documents


3 download

DESCRIPTION

Curso de AOP com AspectJ por Diego Pacheco(http://diego-pacheco.blogspot.com)

TRANSCRIPT

Page 1: Apostila-AspectJ-1.5.4 - Diego Pacheco

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

Diego Pacheco

Dezembro/2007

Page 2: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Page 3: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Page 4: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 5: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Page 6: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

11.. CCoonncceeiittooss BBáássiiccooss ssoobbrree

AAOOPP

Page 7: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 8: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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 cross-cuting 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.

Page 9: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 10: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 11: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 12: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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 <<Nome do pacote se existir>>;

import <<Import java/AspectJ se existir>>;

public aspect <<Nome do aspecto padrão java >> {

// 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 executar qualquer código Java.

Page 13: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 14: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

• 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.

Page 15: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 16: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 17: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 18: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

22.. PPooiinnttccuuttss

Page 19: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 20: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 21: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 22: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 23: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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 co-

variante 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 mesmas limitações.

Page 24: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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, para isso utilizamos reflection, existe uma interface

AnnotatedElement e através dos métodos: getAnnotation(), 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.

Page 25: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 26: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 27: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 28: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

@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.

Page 29: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 30: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 31: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 32: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

33.. AAddvviiccee

Page 33: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Objetivos

• Saber utilizar os tipos de Advices do AspectJ

• Conhecer recursos de ThisJoinPoint

• Saber criar aspectos

• Saber utilizar inner-type declarations

Page 34: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 35: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 36: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 37: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 38: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 39: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 40: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 41: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 42: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 43: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Veja abaixo um exemplo de como podemos utilizar aspectos abstratos e extensão de

aspectos com os recursos da classe utilitária Aspects.

Page 44: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 45: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 46: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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<Porta> Casa.portas = new ArrayList<Porta>();

Código 3.15 – Exemplo de adição de atributo em classes com inner-type.

Page 47: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

No exemplo acima está sendo adicionda uma List<Porta> 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.

Page 48: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 49: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 50: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

44.. RReeccuurrssooss AAddiicciioonnaaiiss

Page 51: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Objetivos

• Saber utilizar AspectJ com annotations.

• Saber utilizar o recurso de declare soft.

• Conhecer o conceito DBC.

Page 52: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 53: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

@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 atributo throwing.

Page 54: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 55: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Considere a seguinte classe Java.

package br.com.targettrust.aop.annotation.innertype.clazz;

public class SimpleCalc {

public int soma(int a,int b) { return a+b; }

public int sub(int a,int b) { return a-b; }

public int multi(int a,int b) { return a*b; }

public int div(int a,int b) { return 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.

Page 56: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 57: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 58: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

determinar quais classes ficaram com erros. Claro que também é necessário um String

do tipo final para ser a mensagem de erro.

Page 59: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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:

Page 60: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 61: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 62: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 63: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 64: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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ós-

condições e invariantes.

Page 65: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 66: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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.

Page 67: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

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

Page 68: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM

Espaço para Anotações

Page 69: Apostila-AspectJ-1.5.4 - Diego Pacheco

AOP – AspectJ 1.5.4 – Programação Orientada a Aspectos

HTTP://DIEGO-PACHECO.BLOGSPOT.COM