O Spring AOP (Prograamção Orientada a Aspectos) é uma técnica que permite modularizar funcionaldiades transversais, como logging ou controle de transações, separando-as da lógica principal do negócio. Esses módulos, chamados aspectos, são aplicados dinamicamente em pontos específicos da execução do programa.
Conceitos Essenciais do AOP
Aspecto: Um módulo que encapsula pointcuts e advices, definindo comportamentos a serem aplicados.
Ponto de Junção: Um ponto executável no código, como uma chamada de método, onde um advice pode ser aplicado.
Pointcut: Uma expressão que seleciona um conjunto de pontos de junção, determinando onde os advices serão inseirdos.
Advice: A ação concreta executada em um ponto de junção, podendo ser antes, depois ou ao redor da execução.
Objeto Alvo: A instância da classe que recebe o advice durante o teçimento.
Teçimento: O processo de combinar aspectos com objetos alvo para produzir objetos aconselhados.
Implementação Prática
A seguir, um exemplo completo ilustrando a configuração do Spring AOP usando XML.
Definição da Interface
package com.demo.spring.aop;
public interface Cliente {
void registrarCliente(String nome);
}
Classe de Implementação
package com.demo.spring.aop;
public class ClienteImpl implements Cliente {
@Override
public void registrarCliente(String nome) {
System.out.println("Cliente registrado: " + nome);
}
}
Aspecto Personalizado
package com.demo.spring.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class AspectoCliente {
// Executa antes do método alvo
public void preProcessamento(JoinPoint ponto) {
String classeAlvo = ponto.getTarget().getClass().getSimpleName();
String metodo = ponto.getSignature().getName();
String argumento = (String) ponto.getArgs()[0];
System.out.println("Preparando para registrar: Classe=" + classeAlvo + ", Método=" + metodo + ", Dado=" + argumento);
}
// Executa após o método alvo
public void posProcessamento(JoinPoint ponto) {
System.out.println("Registro concluído para: " + ponto.getArgs()[0]);
}
// Envolve a execução do método alvo
public Object execucaoCompleta(ProceedingJoinPoint ponto) throws Throwable {
System.out.println("Início do processo de registro");
Object resultado = ponto.proceed();
System.out.println("Fim do processo de registro, resultado=" + resultado);
return resultado;
}
// Notificação após retorno bem-sucedido
public void aposSucesso(JoinPoint ponto) {
System.out.println("Operação bem-sucedida");
}
// Notificação em caso de exceção
public void aposErro(JoinPoint ponto, Throwable excecao) {
System.out.println("Erro durante a operação: " + excecao.getMessage());
}
}
Configuração Spring via 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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="clienteImpl" class="com.demo.spring.aop.ClienteImpl"/>
<bean id="aspectoCliente" class="com.demo.spring.aop.AspectoCliente"/>
<aop:config>
<aop:aspect id="meuAspecto" ref="aspectoCliente">
<aop:pointcut id="corteClientes" expression="execution(* com.demo.spring.aop.*.*(..))"/>
<aop:before method="preProcessamento" pointcut-ref="corteClientes"/>
<aop:after method="posProcessamento" pointcut-ref="corteClientes"/>
<aop:around method="execucaoCompleta" pointcut-ref="corteClientes"/>
<aop:after-returning method="aposSucesso" pointcut-ref="corteClientes"/>
<aop:after-throwing method="aposErro" pointcut-ref="corteClientes" throwing="excecao"/>
</aop:aspect>
</aop:config>
</beans>
Classe de Teste
package com.demo.spring.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AplicacaoTeste {
public static void main(String[] args) {
ApplicationContext contexto = new ClassPathXmlApplicationContext("config-aop.xml");
Cliente cliente = (Cliente) contexto.getBean("clienteImpl");
cliente.registrarCliente("Maria Souza");
}
}
Saída Esperada
Ao executar o teste, o console exibirá mensagens de log dos diferentes advices, demonstrando a aplicação dos aspectos antes, durante e após a chamada do método registrarCliente.