Back-End

24 jul, 2013

Série Spring: Spring Aspect Object Programming – AOP

Publicidade

Olá, pessoal! O artigo de hoje veremos com brincar com AOP. Opsss… O que é isso? Veremos um pouco mais a seguir a utilidade de usar AOP e faremos um exemplo simples para vê-lo em ação.

AOP – Aspect Object Programming

Em poucas palavras, a orientação a aspectos surgiu para eliminar os chamados de cross cutting concerns, ou seja, aquele código que é necessário, mas que não faz parte das principais obrigações do objeto, por exemplo: logging, transação etc. E para isso precisamos entender três pontos apenas:

  1. Advice: separa o código nada a ver em um lugar específico;
  2. Join point: define dentro do advice o momento que o código separado executa;
  3. Point cuts: é onde será feito.

Então o advice é o que será feito. O joint cuts é quando será feito. E o point cuts é onde será feito.

Antes de começar, precisamos fazer o download do .jar do AspectJ. Após baixar, descompacte o .jar com o winrar, por exemplo, e vá na pasta lib, copie os .jars existentes e adicione ao seu projeto.

Precisamos também do AOP Alliance e faça o download. Logo depois, adicione ao seu projeto.

Adicione também o commons-logging-1.x:

AOPBankProject1

Não é diferente do que vimos no primeiro artigo. O objetivo da nossa aplicação é apenas logar informações quando um saque ou despósito for realizado. No exemplo, logamos isso no console, em uma aplicação logaríamos isso em arquivo de log por exemplo.

Desenvolvimento

1. Crie o bean a seguir:

[java]package br.com.camilolopes.bean;

import java.math.BigDecimal;

public class Client {

public void sacar(BigDecimal value) {

System.out.println(“Saque realizado com sucesso ” + value);

}

public void depositar(BigDecimal value) {

System.out.println(“Deposito realizado ” + value);

}}[/java]

2. Agora vamos passar a responsabilidade para o Spring cuidar do nosso bean:

[xml]<?xml version=”1.0″ encoding=”UTF-8″?>

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

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd”>

<bean id=”client” />

<bean class=”br.com.camilolopes.manager.ManagerTransationAccount”/>

<aop:aspectj-autoproxy />

</beans>[/xml]

Há uma pequena mudança no nosso arquivo xml. Observe que adicionamos ao cabeçalho xmlns e http referente aop. E em seguida criamos um bean para cada classe. A ManagerTransationAccount ainda não criamos, mas não há problemas em colocá-la no xml. Vamos criar um pouco mais adiante. Com a tag de proxy que adicionamos acima estamos falando para o Spring fazer o trabalho duro de criar proxy para nós.

Agora vamos criar a nossa classe que vai controlar as mensagens, ou seja, tudo que acontece na conta será logado:

[xml]@Aspect

public class ManagerTransationAccount {

@Pointcut(“execution(* *.sacar(..)”)

public void transacao(){}

@Before(“transacao()”)

public void saque(){

// poderia logar a info no arquivo de log

System.out.println(“Transação de saque inicializada”);

}

@AfterReturning(“transacao()”)

public void retirada(){

System.out.println(“Transação de saque concluida com sucesso”);

}

&nbsp;

@Pointcut(“execution(* *.depositar(..))”)

public void deposito(){}

&nbsp;

@Before(“deposito()”)

public void depositar(){

System.out.println(“Transação de deposito iniciada”);

}

&nbsp;

@AfterReturning(“deposito()”)

public void depositado(){

System.out.println(“deposito realizado com sucesso”);

}

}[/xml]

A anotação na classe é bem intuitiva certo? É preciso dizer que esta classe é orientada a aspect, por isso a anotação no início dela. Em seguida criamos um método da classe. É ai que tudo começa e o segredo está na anotação. Observe que é um pointcut, ou seja, onde será feito o trabalho e ali estamos dizendo que será feito quando o método sacar for chamado de qualquer classe, passando qualquer parâmetro.

Atenção: nenhum método criado nessa classe tem relação com os métodos que criamos na interface Machine. Poderíamos aqui chamar nosso método de qualquer coisa. O segundo que criamos e chamamos de saque que leva anotação @Before diz o seguinte: antes de chamar transacao(), ou seja, o métod que tem o pointcut, execute este aqui, ou seja, vai imprimir no console uma mensagem. Mas, poderíamos gravar uma informação no arquivo de log. As demais anotações falam por si só.

Agora, vamos testar. Crie uma classe com método main:

[xml]public class MainBankMachine {

public static void main(String[] args) {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“conf/springconfiguration.xml”);

Client bean = (Client) applicationContext.getBean(“client”);

bean.sacar(BigDecimal.TEN);

&nbsp;

}

}[/xml]

O resultado

aopresult-300x200

Agora fazendo depósito e saque:

aopresult2-300x276

[xml]public static void main(String[] args) {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“conf/springconfiguration.xml”);

Client bean = (Client) applicationContext.getBean(“client”);

bean.sacar(BigDecimal.TEN);

bean.depositar(BigDecimal.ONE);

}[/xml]

Bom, é isso. Bem mais simples e fácil de dar manutenção, não?

Abraços!