AOP basado en @AspectJ con Spring

@AspectJ se refiere a un estilo de declaración de aspectos como clases regulares de Java anotadas con anotaciones de Java 5. El soporte @AspectJ se habilita al incluir el siguiente elemento dentro de su archivo de configuración basado en esquema XML.

<aop:aspectj-autoproxy/>

También necesitará las siguientes bibliotecas de AspectJ en la ruta de clases de su aplicación. Estas bibliotecas están disponibles en el directorio 'lib' de una instalación de AspectJ; de lo contrario, puede descargarlas de Internet.

  • aspectjrt.jar
  • aspectjweaver.jar
  • aspectj.jar
  • aopalliance.jar

Declarar un aspecto

Las clases de aspectos son como cualquier otro bean normal y pueden tener métodos y campos como cualquier otra clase, excepto que se anotarán con @Aspect de la siguiente manera:

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {
}

Se configurarán en XML como cualquier otro bean de la siguiente manera:

<bean id = "myAspect" class = "org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>

Declarar un pointcut

UN pointcutayuda a determinar los puntos de unión (es decir, los métodos) de interés que se ejecutarán con diferentes consejos. Mientras se trabaja con la configuración basada en @ AspectJ, la declaración pointcut tiene dos partes:

  • Una expresión de corte puntual que determina exactamente en qué ejecuciones de método estamos interesados.

  • Una firma de corte de puntos que comprende un nombre y cualquier número de parámetros. El cuerpo real del método es irrelevante y, de hecho, debería estar vacío.

El siguiente ejemplo define un punto de acceso llamado 'businessService' que coincidirá con la ejecución de todos los métodos disponibles en las clases del paquete com.xyz.myapp.service -

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature

El siguiente ejemplo define un punto de acceso llamado 'getname' que coincidirá con la ejecución del método getName () disponible en la clase Student en el paquete com.tutorialspoint -

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.tutorialspoint.Student.getName(..))") 
private void getname() {}

Declarar consejos

Puede declarar cualquiera de los cinco consejos utilizando las anotaciones @ {NOMBRE-CONSEJO} como se indica en el fragmento de código. Esto supone que ya ha definido un método de firma pointcut businessService () -

@Before("businessService()")
public void doBeforeTask(){
   ...
}

@After("businessService()")
public void doAfterTask(){
   ...
}

@AfterReturning(pointcut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal) {
   // you can intercept retVal here.
   ...
}

@AfterThrowing(pointcut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex) {
  // you can intercept thrown exception here.
  ...
}

@Around("businessService()")
public void doAroundTask(){
   ...
}

Puede definir un corte de punto en línea para cualquiera de los consejos. A continuación se muestra un ejemplo para definir el corte de puntos en línea para el consejo anterior:

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
   ...
}

@AspectJ Ejemplo de AOP basado

Para comprender los conceptos mencionados anteriormente relacionados con el AOP basado en @AspectJ, escribamos un ejemplo que implementará algunos de los consejos. Para escribir nuestro ejemplo con algunos consejos, tengamos un IDE de Eclipse en funcionamiento y sigamos los siguientes pasos para crear una aplicación Spring:

Pasos Descripción
1 Cree un proyecto con un nombre SpringExample y cree un paquete com.tutorialspoint bajo elsrc carpeta en el proyecto creado.
2 Agregue las bibliotecas Spring requeridas usando la opción Agregar JAR externos como se explica en el capítulo Ejemplo de Spring Hello World .
3 Agregar bibliotecas específicas de Spring AOP aspectjrt.jar, aspectjweaver.jar y aspectj.jar en el proyecto.
4 Crea clases de Java Logging, Student y MainApp en el paquete com.tutorialspoint .
5 Cree el archivo de configuración de Beans Beans.xml bajo elsrc carpeta.
6 El paso final es crear el contenido de todos los archivos Java y el archivo de configuración de Bean y ejecutar la aplicación como se explica a continuación.

Aquí está el contenido de Logging.javaarchivo. En realidad, esto es una muestra del módulo de aspecto que define los métodos que se llamarán en varios puntos.

package com.tutorialspoint;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;

@Aspect
public class Logging {
   /** Following is the definition for a pointcut to select
      *  all the methods available. So advice will be called
      *  for all the methods.
   */
   @Pointcut("execution(* com.tutorialspoint.*.*(..))")
   private void selectAll(){}

   /** 
      * This is the method which I would like to execute
      * before a selected method execution.
   */
   @Before("selectAll()")
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
      * This is the method which I would like to execute
      * after a selected method execution.
   */
   @After("selectAll()")
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
      * This is the method which I would like to execute
      * when any method returns.
   */
   @AfterReturning(pointcut = "selectAll()", returning = "retVal")
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
      * This is the method which I would like to execute
      * if there is an exception raised by any method.
   */
   @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }
}

A continuación se muestra el contenido de la Student.java archivo

package com.tutorialspoint;

public class Student {
   private Integer age;
   private String name;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
	  System.out.println("Age : " + age );
      return age;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      System.out.println("Name : " + name );
      return name;
   }
   public void printThrowException(){
      System.out.println("Exception raised");
      throw new IllegalArgumentException();
   }
}

A continuación se muestra el contenido de la MainApp.java archivo

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      
      Student student = (Student) context.getBean("student");
      student.getName();
      student.getAge();
      
      student.printThrowException();
   }
}

A continuación se muestra el archivo de configuración Beans.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.0.xsd 
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <aop:aspectj-autoproxy/>

   <!-- Definition for student bean -->
   <bean id = "student" class = "com.tutorialspoint.Student">
      <property name = "name" value = "Zara" />
      <property name = "age"  value = "11"/>      
   </bean>

   <!-- Definition for logging aspect -->
   <bean id = "logging" class = "com.tutorialspoint.Logging"/> 
      
</beans>

Una vez que haya terminado de crear los archivos de configuración de fuente y bean, ejecutemos la aplicación. Si todo está bien con su aplicación, imprimirá el siguiente mensaje:

Going to setup student profile.
Name : Zara
Student profile has been setup.
Returning:Zara
Going to setup student profile.
Age : 11
Student profile has been setup.
Returning:11
Going to setup student profile.
Exception raised
Student profile has been setup.
There has been an exception: java.lang.IllegalArgumentException
.....
other exception content