Spring AOP

Hace algunos años los aspectos estuvieron muy de moda. Los aspectos nos permiten capturar el acceso a elementos de código e introducir aspectos que alteren o completen el comportamiento del elemento aconsejado. Por ejemplo, nos puede interesar escribir un mensaje de log, antes de entrar en la ejecución de un determinado método, o puede que nos interese abrir una transacción antes de entrar en un método y hacer commit al salir de dicho método. Podemos emplear AOP para conseguir esto sin necesidad de alterar el código de las clases objetivo.

Veamos la nomenclatura utilizada:

  • Consejo: (advice) es el código que se quiere introducir, el trabajo que va a realizar el aspecto
  • Puntos de entrada y puntos de corte: (join points/pointcuts). El primero indica los puntos del código donde se puede aplicar un aspecto y el
    punto de corte es el punto de entrada seleccionado para aplicar el aspecto.
  • Aspecto: (aspect) es la asociación del consejo con el punto de corte.
  • Introducción: (introduction) introducir nuevos métodos o atributos a clases existentes

Dependencias Maven para AOP

Para los ejemplos, emplearemos las siguientes dependencias

 Escribiendo puntos de corte

Los puntos de corte se indican con expresiones AspectJ. El elemento más importante es “execution()“, que indica el punto de corte al que se aplica el punto de corte. Otros elementos como “within()“, “target()“, “this()“, etc., permiten filtrar los resultados. Veamos un ejemplo:

El asterisco indica el tipo devuelto, en este caso, cualquier tipo. Seguidamente se indica el nombre de la clase y el método a capturar. Con los dos puntos se indica que puede recibir cualquier argumento.
Si quisiésemos indicar que además de lo anterior, la invocación del método se debe realizar desde alguna clase que esté en el paquete com.notodocodigo.aop, realizaríamos lo siguiente:

De igual manera, podríamos discriminar por el nombre del bean:

 Declarando aspectos en XML y con anotaciones

Veamos un ejemplo, en primer lugar, creamos la clase Comprar.java, que será la clase a la que aplicaremos los aspectos:

Vamos a capturar la ejecución del bean compra de modo que antes de que se ejecute el método “compra()” se compruebe la cantidad y después de que se ejecute, empaquetemos el producto. También realizaremos otra acción el caso de que en el proceso de compra se produzca un error. Esta seré la clase que utilizaremos para implementar el consejo:

Ahora solo queda definir el la configuración del aspecto:

 

Como se puede ver, con aop:pointcut indicamos el punto de corte, en este caso la ejecución del método “compra()“. Con aop:before, aop:after, etc, se indica cuando se va a aplicar la ejecución del consejo.
Con la siguiente clase, podemos ejecutar el ejemplo:

El resultado es el siguiente:

Si no nos gusta demasiado realizar la configuración en XML, podemos escribir los aspectos con anotaciones, este es el equivalente al ejemplo anterior:

En el ejemplo, el método “pointcut()” va vacío y únicamente se utiliza como referencia al punto de corte a aplicar. Para que Spring capture las anotaciones introducidas, añadiremos esto en el fichero de configuración:

Declarando around advice

En lugar de ejecutar código antes o después del método aconsejado, lo que vamos a realizar es implementar un consejo que envuelva a dicho método. Para ello, vamos a cambiar la clase ValidarMaterial, de este modo:

Como se puede ver con joinpoint.proceed() realizamos la invocación al método que se ha interceptado, lo que nos permite realizar cosas antes y después de la ejecución del método. El ejemplo sería el equivalente al caso anterior, además extraemos el valor del parámetro que recibe el método. La configuración xml, quedará del siguiente modo:

Al ejecutar el ejemplo, obtenemos el siguiente resultado, donde podemos ver el parámetro que recibe:

Al igual que el apartado anterior, vamos a ver como se realizaría lo mismo con anotaciones:

Introduciendo métodos

Una de las herramientas más útiles que se pueden utilizas en AOP es la introducción de métodos. La introducción de métodos nos permite conseguir que una clase implemente un determinado método, sin necesidad de que modifiquemos dicha clase. Vamos a modificar un poco los ejemplos que hemos visto, en primer lugar definimos el aspecto:

Como se puede ver, estamos indicando que todas las clases que implementen el interfaz “com.notodocodigo.aop.Compra“, además van a implementar el interfaz “com.notodocodigo.aop.Pagar“. Y además estamos indicando que el bean que implementará dicha interfaz será el bean “pagador”. Veamos el interfaz:

Y ahora la implementación:

Para ejecutar el ejemplo, escribimos lo siguiente:

El resultado es el siguiente:

Aquí terminamos el artículo. Si queréis comentar algo no dudéis en poner un comentario. Recordad que los comentarios son moderados, así que no se mostrarán inmediatamente en el blog. Podéis ver más artículos sobre Spring aquí

2 comentarios:

  1. Tutorial perfecto. Explicado paso a paso, con un ejemplo sencillo y comentando cada captura. Lo mejor que te puedes encontrar en Internet.

    Muchas gracias!

  2. Excelente aporte, justo lo que buscaba. Muchas gracias !

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *