Embora as anotações sejam amplamente utilizadas no ecossistema Spring moderno, a configuração de Programação Orientada a Aspectos (AOP) via XML continua sendo uma alternatvia robusta, especialmente para centralizar a lógica de infraestrutura sem moidficar o código-fonte das classes de negócio. O funcionamento interno é idêntico ao modelo baseado em anotações, mas a declaração dos join points e advices é feita inteiramente no arquivo de configuração do Spring.
Definição da Classe de Aspecto
Diferente do modelo com anotações, a classe de aspecto em uma configuração XML é um POJO (Plain Old Java Object) comum. Ela não requer nenhuma marcação especial do Spring em seu código-fonte.
package br.com.exemplo.aspecto;
public class MonitoramentoAspecto {
public void registrarInicio() {
System.out.println("[AOP] Iniciando execução do método...");
}
public void registrarFim() {
System.out.println("[AOP] Finalizando execução do método (independente do resultado).");
}
public void tratarErro(Exception ex) {
System.out.println("[AOP] Ocorreu uma exceção: " + ex.getMessage());
}
public void registrarSucesso(Object resultado) {
System.out.println("[AOP] Execução concluída com sucesso. Retorno: " + resultado);
}
}
Configuração do Contexto XML
Para habilitar o suporte a AOP via XML, é obrigatório incluir o namespace aop no cabeçalho do arquivo de configuração. Dentro do elemento <aop:config>, definimos como o aspecto se integra ao fluxo da aplicação.
<?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">
<!-- Definição dos beans -->
<bean id="meuAspecto" class="br.com.exemplo.aspecto.MonitoramentoAspecto" />
<bean id="servicoUsuario" class="br.com.exemplo.servico.impl.UsuarioServiceImpl" />
<!-- Configuração AOP -->
<aop:config>
<aop:aspect ref="meuAspecto">
<!-- Definição do Pointcut: intercepta qualquer método em UsuarioServiceImpl -->
<aop:pointcut id="pontoDeEntrada"
expression="execution(* br.com.exemplo.servico.impl.UsuarioServiceImpl.*(..))" />
<!-- Advices referenciando o pointcut -->
<aop:before method="registrarInicio" pointcut-ref="pontoDeEntrada" />
<aop:after method="registrarFim" pointcut-ref="pontoDeEntrada" />
<aop:after-returning method="registrarSucesso" pointcut-ref="pontoDeEntrada" returning="resultado" />
<aop:after-throwing method="tratarErro" pointcut-ref="pontoDeEntrada" throwing="ex" />
</aop:aspect>
</aop:config>
</beans>
Execução e Teste do Componente
Ao carregar o contexto do Spring, o contêiner criará proxies dinâmicos para os beans que correspondem aos pointcuts definidos. Ao invocar um método do serviço, as ações do aspecto serão disparadas automaticamente de acordo com a configuração XML.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import br.com.exemplo.servico.UsuarioService;
import br.com.exemplo.modelo.Usuario;
public class AppPrincipal {
public static void main(String[] args) {
ApplicationContext contexto = new ClassPathXmlApplicationContext("spring-config.xml");
UsuarioService service = contexto.getBean(UsuarioService.class);
Usuario user = new Usuario();
user.setNome("Dev Senior");
user.setEmail("senior@tech.com");
// Esta chamada acionará os interceptores definidos no XML
service.salvarUsuario(user);
}
}
A principal vantagem desta abordagem é a separação total entre o código de negócio e a configuração de infraestrutura. Caso seja necessário alterar a estratégia de log ou monitoramento, basta modificar o arquivo XML, sem a necessidade de recompilar as classes de serviço ou o próprio aspecto.