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>