You are on page 1of 69

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

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

HTTP://DIEGO-PACHECO.BLOGSPOT.COM
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 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.

HTTP://DIEGO-PACHECO.BLOGSPOT.COM
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, 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.

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

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

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

HTTP://DIEGO-PACHECO.BLOGSPOT.COM
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 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.

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ós-
condiçõ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

You might also like