viernes, 5 de febrero de 2010

Creación de Aspectos con Spring e Interfaces

En los anteriores post comenté como se pueden implementar aspectos mediante anotaciones y en forma declarativa mediante xml, ahora lo vamos a hacer mediante interfaces y unas cuantas declaraciones xml. Veamos; en los aspectos declarados con el tag <aspect> la clase java era un simple javabean, en este post vamos a ver que para evitar el uso de <aspect la clase java que define el aspecto debe de implementar al menos una interface de las siguientes para que las implementaciones de la interface definan el aspecto en la clase, estas interfaces son las siguientes: MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice, el primero de ellos me sirve si quiero que mi clase aspecte métodos antes de que estos se ejecuten, si la clase implementa AfterReturningAdvice entonces el aspecto se ejecutará al finalizar satisfactoriamente la ejecución del método aspectado y finalmente la implementación de la interface ThrowsAdvice capturará las posibles excepciones que el método aspectado lance. Los aspectos son los siguientes:

AuditoriaAspectImpl.java
package pe.com.slcsccy.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

public class AuditoriaAspectImpl
implements MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{

/* Aspecto llamado antes de la ejecución del método que lo ejecuta.
* @param metodo: método que lanza la ejecución de este aspecto.
* @param argumentos: Listado de argumentos del método, debemos hacer el cast.
* @param instancia: Instancia que contiene el método y ejecuta el aspecto.
* */
@Override
public void before(Method metodo, Object[] argumentos, Object instancia)
throws Throwable {
System.out.println("Auditoria.before(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}
/* Aspecto llamado cada vez que la ejecución del método termina con excepción.
* @param metodo: método que lanza la ejecución de este aspecto.
* @param argumentos: Listado de argumentos del método, debemos hacer el cast.
* @param instancia: Instancia que contiene el método y ejecuta el aspecto.
* @param exception: Instancia de la excepción que fué lanzada por el aspecto.
* */
public void afterThrowing(Method metodo, Object[] argumentos, Object instancia, Exception exception){
System.out.println("Auditoria.afterThrowing(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}
/* Aspecto llamado cada vez que la ejecución del método termina satisfactoriamente.
* @param retorno: Instancia que retorna el método.
* @param metodo: método que lanza la ejecución de este aspecto.
* @param argumentos: Listado de argumentos del método, debemos hacer el cast.
* @param instancia: Instancia que contiene el método y ejecuta el aspecto.
* */
@Override
public void afterReturning(Object retorno, Method metodo, Object[] argumentos,
Object instancia) throws Throwable {
System.out.println("Auditoria.afterReturning(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}
}


ImpresorAspectImpl.java
package pe.com.slcsccy.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

public class ImpresorAspectImpl implements MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{

@Override
public void before(Method metodo, Object[] argumentos, Object instancia)
throws Throwable {
System.out.println("Impresor.before(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}
public void afterThrowing(Method metodo, Object[] argumentos, Object instancia, Exception exception){
System.out.println("Impresor.afterThrowing(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}
@Override
public void afterReturning(Object retorno, Method metodo, Object[] argumentos,
Object instancia) throws Throwable {
System.out.println("Impresor.afterReturning(..), metodo:"+metodo.getName()+",instancia:"+instancia.getClass().getCanonicalName());
}

}


Y la configuración de spring es la siguiente:

<!-- Le indicamos a spring para que haga uso de las anotaciones @Autowired -->
<context:annotation-config/>
<!-- Le indicamos a spring que lea todas las clases bajo el paquete pe.com.slcsccy.service y sus
subpaquetes y clases, y si encuentra anotaciones estereotipadas(@Service,@Repository,@Controller)
a nivel de clase entonces cree beans del tipo singleton instanciandolas y disponiendolas al proyecto -->
<context:component-scan base-package="pe.com.slcsccy.service"/>
<!-- La definición del aspecto está embebida al implementar las interfaces *Advice -->
<bean id="impresorAspect" class="pe.com.slcsccy.aop.ImpresorAspectImpl"/>
<bean id="auditoriaAspect" class="pe.com.slcsccy.aop.AuditoriaAspectImpl"/>
<!-- Definición y configuración de los aspectos, cuando se ejecutan y su orden -->
<aop:config>
<aop:pointcut id="pointcut"
expression="execution(public * pe.com.slcsccy.service..*(..))"/>
<!-- El orden de ejecución de los aspectos en conforme ellos son declarados -->
<aop:advisor id="advisor1" advice-ref="auditoriaAspect" pointcut-ref="pointcut"/>
<aop:advisor id="advisor2" advice-ref="impresorAspect" pointcut-ref="pointcut"/>
</aop:config>

1 comentario:

  1. Hola Carlos, la programación orientada a aspectos que aporta a la programación normal (orientada a objetos) en java

    ResponderBorrar

Es bueno comunicarnos, comenta!!.