AspectJ Modularização de interesses ortogonais Heliomar Kann da Rocha Santos Sumário Introdução O que é POA História Terminologias Construções Modelagem Aplicação Controle Transacional Execução de Buscas genéricas em DAO Padrões de projeto com aspectj Auditoria e log de eventos Outras aplicações Tratamento de Exceções Declaração de erros e warnings Implementação default de interfaces Conclusão Conclusão e trabalhos futuros Introdução – O que é POA Introdução – Composição POA Linguagem de componentes: Java, C++.. Linguagem de aspectos: AspectJ.. Programas escritos em linguagem de componentes Programas escritos em linguagem de aspectos Combinador de aspectos: aspect weaver Introdução - História Criada em 1997 Xerox Palo Alto Research Center PARC Atualmente é um projeto Eclipse Modularização de interesses difíceis em POO Introdução - Terminologia Interesses Ortogonais Introdução - Terminologia Interesses Ortogonais Interesses Introdução - Construções Aspect Abstração criada para conter o código de interesses ortogonais em um local separado Semelhança com o “class”, porém não é instanciável Composto por : Join Points Pointcuts Advices, Introdução - Construções Join Points (Ponto de Junção) Pontos bem definidos do código Chamadas a métodos, construtores Execuções de métodos Inicialização e pré-inicialização de Classes Atribuições Introdução - Construções Pointcut (Ponto de atuação) Delimita pontos de junção aos quais algum aspecto provavelmente será aplicado Estrutura pointcut nomePointcut(ListaParametros) : ListaDesignadores Ex.: pointcut construtores() : call(* *.new(..)); pointcut construtores2() : construtores() && !within(Pessoa) ; Introdução - Construções Pointcut (Ponto de atuação) Designadores de pointcut call(Assinatura) – métodos e construtores execution(Assinatura) – métodos e construtores within(Padrão Tipo) – Classe ou tipo em tempo de compilação withincode(Padrão Tipo) – Interno a um método em tempo de compilação args(Padrão Tipo) – Argumentos descritos em “Padrão Tipo” Introdução - Construções Pointcut (Ponto de atuação) Designadores de pointcut target(Padrão Tipo) – Objeto na qual se encontra a implementação do ponto de junção em tempo de execução Ex: pointcut abc() : execution(* getPessoa*(..)) && target(PessoaService) this(Padrão Tipo) - Objeto na qual se encontra o ponto de junção em tempo de execução Ex: pointcut abc() : execution(* getPessoa*(..)) && this(PessoaService) || this(FuncionarioService) Introdução - Construções Wildcards (Caracteres curingas) “*” “..” Qualquer seqüência de caracteres não contendo pontos Qualquer seqüência de caracteres, inclusive contendo pontos “+” Qualquer subclasse da classe em questão Introdução - Construções Pointcuts genéricos call (* set*(..)) execution(public * Pessoa.*(..)) call(* dao..*(..)) call(PessoaDAO+.new(..)) Introdução - Construções Advices (Adendos) Três tipos: Before After Mais simples 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 ter lançado uma exceção Around (entorno de) Mais poderoso Pode escolher entre executar o método original Execução do método através da construção proceed() Introdução - Construções Advices (Adendos) 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(); } Introdução - Modelagem Aplicação - Controle Transacional Transação Controle Transacional Aplicação - Controle Transacional Controle de Transação com Proxy Aplicação - Controle Transacional Controle de Transação com AspectJ Aplicação - Controle Transacional Controle de Transação com AspectJ pointcut transacao(): (@Transacional * *.*(..)); before() : transacao(){ JPAUtil.beginTransaction(); } after()returning : transacao() { JPAUtil.commitTransaction(); JPAUtil.closeEntityManager(); } after() throwing : transacao() { JPAUtil.rollbackTransaction(); } Aplicação – Buscas Genéricas • Anotações Criadas • @MetodoRecuperaLista • @MetodoRecuperaUltimo • @MetodoRecuperaPrimeiro • @MetodoRecuperaConjunto • @MetodoResultadoUnico Aplicação – Buscas Genéricas • Buscas genéricas com Proxy Aplicação – Buscas Genéricas • Buscas genéricas com AspectJ Aplicação – Buscas Genéricas • Mudanças Necessárias • DAOImpl deixa de ser Abstrata • public Pessoa getByLogin(String login) { throw new MetodoInterceptadoException( "Esse método deve ser implementado via aspecto"); } Aplicação – Buscas Genéricas pointcut buscaLista(JPADaoGenerico dao) : call(@MetodoRecuperaLista * *.*(..)) && target(dao); Object around(JPADaoGenerico dao): buscaLista(dao){ Signature sig = thisJoinPointStaticPart.getSignature(); Method metodo = ((MethodSignature)sig).getMethod(); return dao.buscaLista( metodo, thisJoinPoint.getArgs(), metodo.getAnnotation( MetodoRecuperaLista.class) .namedQuery()); } Aplicação – Padrão de Projeto • Singleton • Anotação criada - @Singleton • ... private Map singletons = new Hashtable(); Object around() : call( (@Singleton+ *).new(..) ) { Class singleton = thisJoinPoint.getSignature().getDeclaringType(); if(singletons.get(singleton)==null){ singletons.put(singleton, proceed()); } return singletons.get(singleton); } Aplicação – Padrão de Projeto … @Singleton public class PessoaService { … public PessoaService(){ … } … } Aplicação – Auditoria e Log de Eventos • Auditoria e Log de Eventos … pointcut services(): execution (public * br.uff.iduff2.service..*.*(..)) && !execution(* ..service.controletransacao..*.*(..)) && !execution(List br.uff.iduff2.service..*.*(..)) &&!execution(* IdentificacaoService.autenticar(..)); pointcut autenticar(): execution(* IdentificacaoService.autenticar(..)); Aplicação – Outras aplicações • Tratamento de Exceções 1________________________________________________________ before(): handler(RuntimeException){ System.out.println("Exceção="+thisJoinPoint.getArgs()[0]); } 2________________________________________________________ declare soft : InterruptedException : withincode(* Principal.main(..)); 3________________________________________________________ after() throwing(Throwable t) throws InfraestruturaException: execution(* dao..*.*(..)){ throw new InfraestruturaException(t); } Aplicação – Outras aplicações • Declaração de erros e warnings • Erros declare error: call( java.util.*.new(..) ): "Não é permitido instanciar objetos da biblioteca [java.util] "; • Warnings declare warning: call( dao..*.new(..) ) && !within(service..*): "Essa construção deve ocorrer em um Server"; Aplicação – Conclusão • • • • Simplicidade Evitar uso excessivo Necessidade de manutenção Competitividade • Trabalhos futuros • Plugin perfeitamente integrado com IDEs • Identificação de interesses ortogonais com IA Dúvidas?