Páginas

domingo, 1 de janeiro de 2012

Tutorial - AOP (Orientação a aspectos) com Spring

A AOP (Programação Orientada a Aspectos) é um útil aparato para desenvolvimento de software. Este aparato serve, normalmente, para tratar as propriedades transversais (cross-cutting concerns) da aplicação. Lógico que sempre temos algumas mentes criativas que conseguem aplicar este conceito em outros contextos.
Aqui vamos ver uma aplicação simples com a utilização do framework Spring. Vamos ver algumas terminologias antes de iniciar nossa aplicação:
Advice: definem oque será executado e quando será executado.
Joinpoints: disponibilizam os pontos onde podemos unir o aspecto à aplicação. Na AOP existem diversos tipo de pontos de junção (Joinpoints) como métodos, atributos, construtores, mas na técnica que vamos ver só existe suporte a métodos.
Poincuts: definem onde será executado o aspecto. Este item une os Joinpoints aos Advices.
Target: como já diz, é o nosso alvo, ou seja, o objeto que será monitorado.
Proxy: é um objeto que vai encapsular todas as chamadas ao nosso objeto alvo (target), disponibilizando, assim, os pontos para notificação dos aspectos.
Weaving: é onde serão aplicados os aspectos em determinados objetos (Target). Existem alguns tipos de Weaving, mas o que nos interessa para este exemplo é o Weaving de tempo de execução onde, geralmente, um objeto proxy é gerado dinamicamente em tempo de execução para o objeto alvo(Target).
Agora que já sabemos alguns itens da terminologia de aspectos vamos criar uma aplicação com a utilização de Spring e seu container AOP.
Eu recomendo fazer download do framework Spring com suas dependências, para não precisar se incomodar com as bibliotecas de dependências do Spring. O link segue abaixo:
Podemos utilizar um aspecto para diversas coisas no sentido transversal da aplicação, desde Log da aplicação, gerenciar transações, verificações de segurança até simplesmente monitorar um objeto. Para nossa aplicação, vamos monitorar um objeto sendo que este pode ser um ponto de partida para abordagens mais complexas dessa tecnologia.
Primeiro vamos criar a classe a ser monitorada. Segue abaixo o fonte de nossa classe:
package org.springframework.aop.sample;
public class Monitorable implements IMonitorable{
@Overridepublic void execute(){
System.out.println("Executing method");
}
}
No caso criamos uma interface para disponibilizar os contratos da nossa classe. Nossa classe, ao executar o método execute, vai imprimir “Executing method”. Agora vamos a classe que irá cuidar de monitorar a classe anterior. Segue o fonte:
package org.springframework.aop.sample;
public class Monitor implements IMonitor{
@Override
public void after(){
System.out.println("Aspecto - after");
}
@Overridepublic void afterThrowing(){
System.out.println("Aspecto - after-throwing");
}
@Overridepublic void before(){
System.out.println("Aspecto - before");
}
}
Podemos que é uma classe simples, fizemos o mesmo que na classe anterior, disponibilizamos os métodos através de uma interface.
Agora vamos fazer a mágica da aplicação. Vamos criar o descritor do Spring para nossa aplicação. Segue o fonte e estaria dando detalhes sobre as notações:
xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
">

<aop:config>
<aop:aspect ref="sampleMonitor">
<aop:pointcut id="daoExec" expression="execution(* org.springframework.aop.sample.IMonitorable.*(..))"/>
<aop:before method="before" pointcut-ref="daoExec"/>
<aop:after method="after" pointcut-ref="daoExec"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="daoExec"/>
aop:aspect>
aop:config>

<bean id="sampleMonitor" class="org.springframework.aop.sample.Monitor"/>
<bean id="sampleMonitorable" class="org.springframework.aop.sample.Monitorable"/>
beans>
Podemos perceber que temos nosso beans declarados ao final do arquivo, como uma declaração normal de beans do Spring. O que existe de diferente no nosso descritor está contigo dentro da tag aop:config. Quase todas as declarações utilizadas com a tag aop do Spring devem ficar dentro de aop:config, mas existem algumas exceções.
A tag aspect indica a declaração de um aspecto e o atributo ref trás uma referencia ao nosso bean sampleMonitor.
A tag pointcut cria a declaração do pointcut do aspecto. Poderíamos criar um pointcut para cada advice através do atributo pointcut, mas queremos poupar trabalho de digitação e centralizar as configurações do pointcut. No atributo expression da tag pointcut fica contida a expressão para procurar os beans que são compatíveis a ela. No caso estamos dizendo que na execução (execution) de um método que retorne qualquer coisa (o primeiro asterisco), que seja um IMonitorable, com qualquer nome de método (segundo asterísco) e que receba qualquer coisa como argumento (..).
Agora vamos aos advices, que são declarados através das tags before, after e after-throwing. Elas indicam quando (o próprio nome do advice indica) a lógica vai ser executada e oquê vai ser executado (através do método method). Podemos ver que todas elas se referenciam ao mesmo pointcut através do atributo pointcut-ref.
É importante prestar atenção nas declarações das tags no início do documento.
Agora vamos criar a nossa classe que vai carregar nosso bean e chamar o método execute. Segue abaixo o fonte da nossa classe:
package org.springframework.aop.sample;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
BeanFactory ctx = new ClassPathXmlApplicationContext("hello.xml");
IMonitorable monitorable = (IMonitorable) ctx.getBean("sampleMonitorable");
monitorable.execute();
}
}
Ao executar este exemplo as saídas serão.
Aspecto – before
Executing method
Aspecto - after
Se gerarmos uma exceção no método execute, o método afterThrowing também será executado. O interessante dessa técnica é que o nosso aspecto é um simples pojo, sem ter dependências de outros projetos.
Bom nosso exemplo está pronto. Até a próxima...

Nenhum comentário:

Postar um comentário