Programación orientada aspectos(AOP)
La programación orientada aspectos (AOP) es un paradigma de programación que complementa la programación orientada a objetos (POO), AOP permite modular conceptos que son trasversales a la aplicación y que con POO son difíciles de encapsular en objetos o funciones. Entiéndase por transversal a conceptos o funcionalidades que están distribuidas por gran parte de la aplicación.
Puede estar tentado a utilizar POO para la implementación de funcionalidades transversales, esto llevara a repetir varias líneas de código en los componentes donde desea implementar la funcionalidad, con las consecuentes dificultades de mantenimiento y desarrollo que ello implica. Más allá de aquello, es que al hacerlo se le esta asignado responsabilidades al componente(clase) que no le compete, ya que por lo general las funcionalidades transversales son propio de la aplicación. Por ejemplo, el sistema de log, el manejo de transacciones, entre otros.
En la literatura AOP a estas funcionalidades trasversales se las denomina preocupaciones transversales.
AOP con Spring
Spring provee el marco Spring AOP y además brinda soporte para el estilo @AspectJ para implementar la AOP. Vamos a centrarnos en construir aspectos con @AspectJ.
Spring utiliza el aspecto como unidad para modular las funcionalidades transversales. Un aspecto es una clase java donde se implementan las diferentes preocupaciones tranversales.
@AspectJ
Este estilo permite definir aspectos mediante clases java con anotaciones, tenga presente que @AspectJ es un marco independiente a Spring, sin embargo, este ultimo brinda un soporte completo para utilizarlo.
Podemos utilizar Spring AOP mediante XML o anotaciones, revisaremos esta última opción que es la forma más común.
Proyecto AOP Spring
Agregamos las siguientes dependencias al pom.xml
-
Agregar dependencia spring-aop
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.15</version> </dependency >
-
Agregar dependencia aspectjweaver
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.8</version> </dependency >
Clase Cliente
Para el ejemplo, defina la siguiente clase
@Component public class Cliente{ public void insertar(){ System.out.println("Insertando el cliente"); } //..... }
Crear un aspecto
Definimos un clase java y agregamos la anotacion @Aspect para definir la clase como un aspecto, además anotamos con @Component para registrar el aspecto como un bean de Spring.
-
@Component @Aspect public class AspectCliente{ // ---- }
Punto de corte(Pointcut)
Los Pointcut son expresiones que indican sobre que metodos, clases o paquetes debe actuar el aspecto. Utilize la anotación @Pointcut sobre un método que este dentro de una clase anotada con @Aspect
La expresión Pointcut debe seguir la siguiente sintaxis:
-
Detalles:
- execution(expresion): permite ejecutar la expresion que se define entre ()
- modificador (opcional): especifica un modificador de acceso (public, private, etc).
- tipo-retorno: especifica un tipo de retorno (void, String, etc).
- tipo-declaracion (opcional): especifica el tipo/clase de la declaración (x.y.Service, x.y.Cliente, etc).
- nombre-metodo: especifica un método sobre el cual el aspecto actuará (loginCliente(), etc).
- parametro : especifica parámetros de la declaración (String, int, etc), o simplemente ().
-
Ejemplo básico
@Pointcut("execution(public void insertar())") // Expresión Pointcut public void logAccion(){} // La Firma(Signature) Pointcut
El Pointcut logAccion() actuará sobre todos los métodos que coincida con la expresión public void insertar().
-
Un @Pointcut consta de dos partes
- Expresion Pointcut: patrón dentro @Pointcut que determina donde actuará
- Firma Pointcut: método sobre el que se anota @Pointcut, debe ser sin retorno(void)
-
Tenga presente que los @Pointcut simplemente son definiciones que determinan donde deberá actuar un aspecto, por ello no llevan lógica en el método de definición.
Consejos (Advice)
Los consejos o advice referencian a uno o varios @Pointcut, un advice determina el momento(antes, despues) en que debe actuar @Pointcut. Tenemos varios tipos de advice:
- @Before: Se ejecuta antes del método
- @AfterReturning: Se ejecuta despues de la ejecución normal del método(Sin que ocurra una excepción)
- @AfterThrowing: Se ejecuta despúes que el método lanze una excepción
- @After: Se ejecuta despúes del método, tanto si se ejecuta normalmente o con excepciones.
- @Around: Se ejecuta alrededor del método, es decir tanto antes como despues.
Un advice debe definirse dentro de un clase anotada con @Aspect.
-
@Before("logAccion()") public void beforeInsert(){ System.out.println("Antes de insertar un cliente") } @After("logAccion()") public void afterInsert(){ System.out.println("Despues de insertar un cliente") }
Los advice @Before y @After estan referenciando al mismo @Pointcut logAccion(), sin embargo, son llamados en momentos diferentes. El primero se ejecutará antes del punto de corte definido por logAccion(), mientras que @After se ejecutará despues de ejecutar el punto de corte.
Habilitar el soporte para @AspectJ
Debe agregar la anotación @EnableAspectJAutoProxy en el contenedor IoC para habilitar la compatibilidad con Spring para configurar Spring AOP.
-
Utilizando anotaciones
@Configuration @ComponentScan(basePackages = "x.y....") @EnableAspectJAutoProxy public class SpringConfig{...}
Recuerde que la clase anotada con @Aspect, tambien fue anotada con @Compontent, no olvide scanearla en @ComponentScan.
-
Mediante XML
<aop:aspectj-autoproxy/>
Para utilizar esta etiqueta debe agregar el name-space de aop, consulte esquema completo para aop para obtener.
Ejecutar programa
Cree un bean de la clase Cliente e invoque al método insertar(), deberá ver la siguiente salida en consola
System.out.println("Antes de insertar un cliente") // Advice @Before System.out.println("Insertando el cliente"); // Ejecución del método System.out.println("Despues de insertar un cliente") // Advice @After
Al invocar al método insertar(), este coincide con el @Pointcut("execution(public void insertar())") del aspecto, el mismo es referenciado por los advice @Before y @After que ejecutarán la logica definida en ellos .
En entradas posteriores revisaremos más sobre este tema
Comentarios
Publicar un comentario