AspectJ
Programação Orientada a Aspectos
Thiago Rodrigo Assumpção de Abreu
Surgimento
• Foi desenvolvida nos laboratórios da Xerox, por uma
divisão de pesquisa denominada Xerox PARC, em 1997.
• A idealização da linguagem se deve a Gregor Kiczales,
professor da University of British Columbia no Canadá.
• Atualmente é mantida pela Fundação Eclipse,
detentora de alguns projetos de código aberto, sendo
integrado na ferramenta de desenvolvimento
Eclipse(IDE).
Por que utilizar AspectJ
• Linguagens de programação procedurais e as
orientadas a objetos não possuem técnicas
suficientemente claras para implementar algumas
decisões de projetos, sem que alguns de seus conceitos
e regras sejam transgredidos.
• O que força a implementação destas decisões de
projeto a serem espalhadas através do código, gerando
um código confuso e difícil de desenvolver e manter.
• Estas decisões de projeto são difíceis de serem tratadas
porque elas vão além das funcionalidades básicas do
sistema, ou seja, não é possível separá-la em um
componente ou uma classe, pois ela “pertence” a todo
sistema.
Singularidade
• O que diferencia AspectJ das demais linguagens de
programação é o fato de não ser possível construir
programas usando somente o AspectJ, sendo
necessário também utilizar outra linguagem.
• Isso vem da própria idéia do paradigma da orientação à
Aspectos, que é customizar programas e solucionar
problemas.
• De certa forma podemos dizer que Aspectj é uma
extensão da linguagem Java, pois usa todos os recursos
da linguagem e acrescenta recursos de Programação
Orientada a Aspectos (POA).
Conceitos Fundamentais
• 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:
– Join points
– Pointcuts
– Advice
Conceitos Fundamentais
• Pontos de junção (Join Points)
– Os pontos de junção são locais bem definidos da
execução de um programa, por exemplo, uma
chamada a um método ou a ocorrência de uma
exceção, dentre muitos outros. Ou seja, são pontos
de programas onde os aspectos e o código Java se
“encontram”.
– A partir dos pontos de junção, são criadas as regras
que darão origem aos pontos de atuação.
Conceitos Fundamentais
• Exemplos de pontos de junção (Join Points):
–
–
–
–
–
–
–
–
–
chamada de métodos;
execução de métodos;
chamada de construtores;
execução de inicialização;
execução de construtores;
execução de inicialização estática;
inicialização de objetos;
referência a campos;
execução de tratamento de exceções.
Conceitos Fundamentais
• Pontos de atuação (Pointscuts)
– São os pontos responsáveis por detectarem quais Join Points o
aspecto deverá interceptar.
– Pointcuts são alguns join points de um programa que são capturados
pelo mecanismo de AOP do AspectJ.
– A captura ocorre baseada em expressões definidas pelo programador.
• Estrutura:
• pointcut nomePointcut(ListaParametros): <<expressao>>;
– Ex.: public aspect PointcutExemplo {
pointcut nomePointcut(): call (void metodoX());
}
• No exemplo acima estamos declarando um pointcut de nome
nomePointcut que irá capturar todas as chamadas ao método metodoX()
de qualquer classe.
Conceitos Fundamentais
• Exemplos de pontos de corte (Pointcuts):
Conceitos Fundamentais
• Operadores Lógicos (&&, ||, !):
public aspect PointcutLogicalOperators {
pointcut operadorAnd(): call ( String
teste.aop.java.domain.model.Pessoa.getNome() )
&&
call ( String teste.aop.java.domain.model.PessoaFisica.getNome() );
pointcut operadorOr(): call ( String
teste.aop.java.domain.model.Pessoa.getNome() )
||
call ( String teste.aop.java.domain.model.Pessoa.getEndereco() );
pointcut operadorNot(): call ( ! String
teste.aop.java.domain.model.Pessoa.getNome() );
}
Conceitos Fundamentais
• Caracteres Curingas (Wildcards):
– ‘*’ Qualquer sequência de caracteres não contendo pontos.
– ‘..’ Qualquer sequência de caracteres, inclusive contendo pontos.
– ‘+’ Qualquer subclasse da classe em questão.
• 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*(..));
• 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.
Conceitos Fundamentais
• 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. 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.
Conceitos Fundamentais
• Exemplos de erros e warnings:
public aspect JoinPointMacthWithAnnotationErrosWarnings {
declare warning :
within(teste.aop.pointcuts.annotation.erroswarnings.java.*)
&& call(* faz*(..))
: "Você não deve chamar metodos com o prefixo faz*";
declare error :
within(teste.aop.pointcuts.annotation.erroswarnings.java.*)
&& call(* deleteAll*(..))
: "Você não deve deletar tudo!!!";
}
Conceitos Fundamentais
• Adendos (Advices)
– Os Pointcuts apenas selecionam os pontos onde o
AspectJ irá interceptar. Para implementar o
comportamento desses pontos de cortes é usado
o advice, ou seja, é através dele que definimos o
trecho de código que será executado a cada
interceptação do Pointcusts.
– Existem três formas de advice: before, around e
after.
Conceitos Fundamentais
• Before:
– Antes da execução do método do pointcut.
• After:
– After – Sempre depois do ponto de junção.
– After Returning – Somente se o método não lançar
exceções.
– After Throwing – Somente se o método lançar uma
exceção.
• Around:
– Durante a execução do método do pointcut.
– Ocorre a execução do método através da construção
proceed().
Conceitos Fundamentais
• Exemplos de Advices:
– Poderíamos gerar um log toda vez que um objeto
for salvo, isso seria detectado pelo Pointcut e esse
código de log estaria em um advice.
• 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.: após gravar um objeto quero logar tudo.
• Around: Durante a execução do método do pointcut:
– Ex.: no momento de gravar um objeto e ele for pessoa jurídica
e maior de 30 anos deve fazer o log.
Conceitos Fundamentais
– Estrutura
• tipoAdvice(ListaParametros) : ListaPointCut(){corpo}
• Ex1:
– before() : call( String *.toString()){
imprime(“Antes de entrar no método toString”);
}
• Ex2:
– pointcut metodosToString() : call(String *.toString());
– String around() : metodosToString() {
return proceed().toUpperCase();
}
Onde aplicar AspectJ
• A POA contribui na implementação dos interesses sistêmicos, que,
mesmo não sendo inerentes ao negócio, são, na maioria dos casos,
indispensáveis para o sucesso da aplicação. Por meio do uso da
orientação a aspectos, esses interesses podem ser agrupados em
unidades modulares, tornando a manutenção mais simples e
facilitando o reúso por reduzir a interdependência entre os
interesses. Dentre as aplicações de interesses sistêmicos, sob a
perspectiva da POA, podemos listar os seguintes itens:
Onde aplicar AspectJ
– Sincronização de objetos concorrentes: a POA disponibiliza um
mecanismo eficaz para modularizar a política de sincronização.
– Distribuição: com a programação orientada a aspectos, pode-se tornar
a distribuição transparente por meio da criação de um aspecto
destinado a representar esse interesse, tornando desnecessária a
refatoração. O aspecto mapeia todo o interesse de distribuição e, por
meio do combinador aspectual, é gerado um código “distribuível”
similar ao que seria o código refatorado.
– Tratamento de exceções: Por meio do uso da POA é possível
centralizar as políticas para tratamento de exceções em unidades
elementares, o que facilita tanto a manutenção e legibilidade das
classes quanto à abordagem para o tratamento de exceções.
– Coordenação de múltiplos objetos: A POA permite modularizar a
lógica destinada a sincronizar a integração entre os objetos ativos em
busca de um objetivo global.
Onde aplicar AspectJ
– Persistência: Por meio do uso de aspectos é possível centralizar e
abstrair a implementação desse interesse da camada de negócio,
facilitando, assim, a manutenção e a obtenção de melhorias nas
abordagens aplicadas.
– Auditoria: Com a POA, o interesse de auditoria pode ser
implementado independentemente da regra de negócio. Dessa forma,
o código estaria em um único local centralizado e bem definido no
sistema, sendo retirado das classes.
Hello Word
public class HelloWorld {
public static void main(String[] args) {
}
}
public aspect HelloFromAspectJ {
pointcut mainMethod() : execution(public static void
main(String[]));
after() returning : mainMethod() {
System.out.println("Hello World");
}
}
99 Bottles
aspect BeerAspect {
static String[][] REPLACE = {
{ "1 bottles", "1 bottle" },
{ "^0", "No more" },
{ "0", "no more" },
{ ".*-1", "Go to the store and buy some more, 99" },
};
99 Bottles
void around (String text, int count) :
call(* *.println(..)) &&
args(text) &&
cflowbelow(call (* Beer.lyrics(..)) && args(count)) &&
!within(BeerAspect) &&
if(count <= 2) {
for (String[] replace : REPLACE) {
text = text.replaceAll(replace[0], replace[1]);
}
proceed(text, count);
}
99 Bottles
after(int count) :
call (* Beer.lyrics(..)) &&
args(count) &&
if (count > 0) {
((Beer)thisJoinPoint.getTarget()).lyrics(count - 1);
}
}
99 Bottles
class Beer {
static final String BEER = " bottles of beer";
static final String BEER_WALL = BEER + " on the wall";
static final String TAKE = "Take one down and pass it around, ";
void lyrics(int count) {
System.out.println(count + BEER_WALL + ", " + count + BEER + ".");
System.out.println(TAKE + (count - 1) + BEER_WALL + ".");
System.out.println();
}
public static void main(String[] args) {
new Beer().lyrics(99);
}
}
Bibliografia
•
•
•
•
•
•
•
•
GOETTEN Junior, WINCK Diogo, 2006. AspectJ – Programação Orientada a Aspectos
com Java. São Paulo – SP: Novatec Editora, 2006.
ASPECTJ Team. Disponível em: <http: / /www.eclipse.org/ aspectj>.
BÖLLERT, Kai. On Weaving Aspects. In the Proceedings of the Aspect Oriented
Programming Workshop at ECOOP'99, 1999.
CHAVEZ, Christina. GARCIA, Alessandro. LUCENA, Carlos. Desenvolvimento
Orientado a Aspectos. Anais do XVII Simpósio Brasileiro de Engenharia de
Software, Manaus Amazonas. Universidade Federal do Amazonas. 2003.
GOETTEN Junior, WINCK Diogo e MACHADO Caio, 2004. Programação Orientada a
Aspectos Abordando Java e aspectJ. Workcomp Sul – SBC.
KICZALES,G.; LAMPING, J.; MENDHEKAR, A.; MAEDA, C. et al. Aspectoriented
programming. Para apresentação em: ECOOP'97, LNCS 1241. Springer, 1997.
PIVETA, Eduardo. Um modelo de suporte a programação orientada a aspectos .
UFSC. Dissertação submetida como parte dos requisitos para a obtenção do grau
de Mestre em Ciência da Computação, 2001.
Wikipédia - <http://pt.wikipedia.org/wiki/AspectJ>
Download

AspectJ