domingo, 31 de enero de 2010

Creación de Aspectos con Spring y Anotaciones Parte 1

Hola denuevo, hace mucho tiempo que no posteo y esta vez quiero seguir con los aspectos en Spring, en este post supongo que ya conocen que es un aspecto, para resumirles y hablando como pragramador es un método java que se ejecuta antes, después o antes y después de la ejecución de otro método java, esto nos permite agregar lógica a nuestra aplicación conociendo únicamente la especificación de los métodos a los cuales se les quiere aplicar un aspecto.
La aplicación de ejemplo que he desarrollado es simple: un servicio impresor de libros que tiene un método imprimir con un parámetro Libro a este método imprimir es al cual le aplico una serie de aspectos para agregar las propiedades del libro(autor, isbn y título), los anotaciones que he usado para aplicar los aspectos son: @Aspect, @Before, @After, @AfterReturning, @AfterThrowing, @Around

La clase principal es la siguiente:

package pe.com.slcsccy.aop;

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

import pe.com.slcsccy.bean.Libro;
import pe.com.slcsccy.service.ImpresorService;

@Aspect
public class ImpresorAspect {

/**
* Este método se ejecuta SIEMPRE antes de cualquier ejecución
* de cualquier método de cualquier clase del paquete pe.com.slcsccy.service y
* que tenga un primer parámetro con nombre libroin
* Obtengo el objeto que viene como parametro y le coloco el nombre del autor,
* además capturo la instancia que disparó el aspecto.
* */
@Before("execution(public * pe.com.slcsccy.service..*(..)) && "+
"args(libroin) && target(instancia)")
public void asignarAutor(Libro libroin, Object instancia) {
if(libroin!=null)libroin.setAutor("Carlos Cacique");
System.out.println("Aplicando Aspecto asignarAutor(..) @Before! con instancia:"+instancia.getClass().getCanonicalName());
}
/**
* Este método se ejecuta SIEMPRE antes de la ejecución de cualquier
* método imprimir que tenga un primer parámetro con nombre libroin de
* cualquier clase que implementa la interface
* pe.com.slcsccy.service.ImpresorService
* */
@Before(value="execution(public * pe.com.slcsccy.service.ImpresorService.imprimir(..)) && "+
"args(libroin) && target(instancia)")
public void asignarISBN(Libro libroin, ImpresorService instancia) {
if(libroin!=null)libroin.setIsbn("41547848");
System.out.println("Aplicando Aspecto asignarISBN(..) @Before! con instancia:"+instancia.getClass().getCanonicalName());
}
/**
* Este método se ejecuta SOLO después de la ejecución EXITOSA de cualquier
* método imprimir que tenga un primer parámetro con nombre libroin
* de cualquier clase que implementa la interface
* pe.com.slcsccy.service.ImpresorService
* */
@AfterReturning(value="execution(public * pe.com.slcsccy.service.ImpresorService.imprimir(..)) && "+
"args(libroin) && target(instancia)",returning="libroOut")
public void asignarTitulo(Libro libroin, Libro libroOut, ImpresorService instancia) {
libroOut.setTitulo("Ejemplo de aspectos con spring");
System.out.println("Aplicando Aspecto asignarTitulo(..) @AfterReturning! con instancia:"+instancia.getClass().getCanonicalName());
System.out.println("Libro Out:"+libroOut);
}
/**
* Este método se ejecuta SIEMPRE después de cualquier
* método imprimir que tenga un primer parámetro con nombre libroin
* de cualquier clase que implementa la interface
* pe.com.slcsccy.service.ImpresorService
* */
@After(value="execution(public * pe.com.slcsccy.service.ImpresorService.imprimir(..)) && "+
"args(libroin) && target(instancia)")
public void finalizarNormal(Libro libroin, ImpresorService instancia) {
System.out.println("Aplicando Aspecto finalizarNormal(..) @After! con instancia:"+instancia.getClass().getCanonicalName());
System.out.println("Libro:"+libroin);
}
/**
* Este método se ejecuta SIEMPRE que ocurre una excepción después de ejecutar
* cualquier método imprimir que tenga un primer parámetro con nombre libroin
* de cualquier clase que implementa la interface
* pe.com.slcsccy.service.ImpresorService
* */
@AfterThrowing(value="execution(public * pe.com.slcsccy.service.ImpresorService.imprimir(..)) && " +
"args(libroin) && target(instancia)",
throwing="excepcion")
public void finalizarConExcepcion(Libro libroin, ImpresorService instancia, ImpresorException excepcion) {
System.out.println("Aplicando Aspecto finalizarConExcepcion(..) @AfterThrowing!");
System.out.println("Mensaje de la Excepcion en el aspecto @AfterThrowing:"+excepcion.getMessage());
}
/**
* Este método se ejecuta dos fases, la primera antes de la ejecución del método y la segunda * cuando el método a terminado satisfactoriamente.
* @throws Throwable
* */
@Around(value="execution(public * pe.com.slcsccy.service.ImpresorService.imprimir(..)) && " +
"args(libroin) && target(instancia)")
public void logging(ProceedingJoinPoint ejecutor,Libro libroin, ImpresorService instancia) throws Throwable {
System.out.println("Iniciando loggin(..) @Around!");
Object retorno = ejecutor.proceed();
System.out.println("Finalizando loggin(..) @Around!, con retorno:"+retorno.getClass().getCanonicalName());
}
}

La aplicación completa en eclipse la puedes descargar desde AQUI.