Anda di halaman 1dari 42

Desarrollo de Aplicaciones

Java con Spring

Fernando Rincn Martn


6. AOP
Programacin Orientada a
Aspectos
Complementa la Programacin Orientada a Objetos.
Clase Aspecto
Permiten la modularizacin de conceptos no
pertenecientes al cdigo de negocio.
Como ejemplo podemos poner el manejo de
transacciones o la auditora.
Spring AOP no es necesario para usar IoC.
Conceptops AOP
Aspect (Aspecto) funcionalidad transversal (varias clases) que se implementa modularizada y separada del resto de
cdigo.
Manejo de Transacciones
Auditora
Logs
Join Point (Punto de Cruce) es un punto de ejecucin dentro del sistema donde un aspecto puede ser conectado,
como por ejemplo la ejecucin de un mtodo o el lanzamiento de una excepcin.
En Spring AOP slo se soportan los puntos de cruce en llamadas a mtodos.
Advice (Consejo) es la implementacin del aspecto, es decir, contiene el cdigo que implementa la nueva
funcionalidad. Existen diferentes tipos de Advice.
Pointcut (Punto de corte) define los Consejos que se aplicarn a cada Punto de Cruce. Un Advice es asociado a una
expresion Pointcut y se ejecuta en cualquier Join Point que coincida con la expresin.
Spring usa el lenguaje de AspectJ
Introduction (Introduccion) declara mtodos adicionales o campos en el tipo. En Spring lo nico que se pueden
introducir son nuevas interfaces (con su implementacin).
Target (Destinatario) - es la clase aconsejada, la clase que es objeto de un consejo.
AOP Proxy el objeto creado por el framework que resulta del cdigo del target ms el cdigo de los consejos.
En Spring ser un JDK dynamic proxy o CGLIB proxy.
Weaving (Tejido) es el proceso de aplicar Aspectos a los Objetos Destinatarios para crear los nuevos Objetos
Resultantes en los especificados Puntos de Cruce.
Se puede realizar en tiempo de compilacin (AspectJ), en tiempo de carga o en tiempo de ejecucin (Spring AOP).
Tipos de Advices
Before advice El consejo se ejecuta antes del punto de cruce, y este no tiene
la posibilidad de cambiar el flujo de ejecucin (que no se ejecute el punto de
cruce) a menos que lance una excepcin.
After returning advice El consejo se ejecuta despus de que el punto de cruce
se haya ejecutado satisfactoriamente.
After throwing advice El consejo se ejecuta despus de que el punto de cruce
haya lanzado una excepcin.
After (finally) advice El consejo se ejecuta cuando termina la ejecucin de
punto de cruce, pudiendo haber lanzado una excepcin o no.
Around advice: El consejo rodea el punto de cruce.
Puede realizar operaciones antes y despues de la llamada al punto de cruce.
Adems puede decidir llamar al punto de cruce o, por el contrario, el consejo puede
devolver su propio valor o lanzar una excepcin.
Ventajas y posibilidades Spring
AOP
Implementado en Java puro.
No es necesario un proceso de compilacin especial.
No necesita realizar cambios al ClassLoader.
Solo soporta los puntos de cruce los mtodos
pblicos.
No es una implementacin completa.
Los aspectos se declaran como beans normales.
Proxy AOP
Spring usa por defecto proxys dinamicos J2SE
estndar.
Posibilidad de introducir consejos en las Interfaces,
NO en las clases.
Proxies CGLIB
Se usan cuando se necesita aconsejar una clase y no
una interfaz.
Declaracin
@AspecJ Anotaciones AspectJ en las clases
advices.
Declaracin mediante XML.
@AspectJ
Usa las librerias AspectJ para poder leer las
anotaciones.
No usa las librerias para implementar el tejido. Esto
se hace con cdigo especifico Spring.
Habilitar @AspectJ
<aop:aspectj-autoproxy/>
Declarar un aspecto
Una vez habilitado, cuarquier bean con la anotacin
@Aspect ser detectado automticamente.
En Spring AOP no se puede aconsejar con un
aspecto otro aspecto.

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">


<!-- configure properties of aspect here as normal -->
</bean>

package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class NotVeryUsefulAspect {

}
Declarar un Pointcut
@Pointcut("execution(* transfer(..))")// the pointcut expression
private void anyOldTransfer() {}// the pointcut signature

@Pointcut
execution(modifiers-pattern? ret-type-pattern declaring-type-
pattern? name-pattern(param-pattern) throws-pattern?)

Spring AOP solo soporta el consejo en


ejecuciones de mtodos.
Siempre debe devolver void
PDC Pointcut Designators
execution Busca los Join Point en mtodos de ejecucin. Es el principal PDC.
within limita la bsqueda de Join Points dentro de ciertos tipos.
this limita la bsqueda a los que la referencia (Proxy AOP) implementen cierta interfaz
target limita la bsqueda a los que el bean implemente cierta interfaz.
args limita la bsqueda a los mtodos cuyos argumentos sean de los tipos especificados.
@target limita la bsqueda a los mtodos de las clases que tengan la anotacin especificada.
@args limita la bsqueda a los mtodos cuyos argumentos tengan la anotacin o anotaciones especificadas.
@within limita la bsqueda a los mtodos declarados en tipos con la anotacin especificada.
@annotation limita la bsqieda a los mtodos que tengan la anotacin especificada.
bean (especfico de Spring) limta la bsqueda a los beans con el nombre especificado.
Poincuts - Ejemplos
execution(public * *(..))

execution(* set*(..))

execution(* com.xyz.service.AccountService.*(..))

execution(* com.xyz.service.*.*(..))

execution(* com.xyz.service..*.*(..))

within(com.xyz.service.*)

within(com.xyz.service..*)

this(com.xyz.service.AccountService)

target(com.xyz.service.AccountService)

args(java.io.Serializable)
Pointcuts Ejemplos
@target(org.springframework.transaction.annotation.Transactional)

@within(org.springframework.transaction.annotation.Transactional)

@annotation(org.springframework.transaction.annotation.Transactional)

@args(com.xyz.security.Classified)

bean(tradeService)

bean(*Service)
Combinar Pointcuts
Se pueden usar los operadores '&&', '||' y '!' para
combinar Poincuts.
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}

@Pointcut("anyPublicOperation() && inTrading()")


private void tradingOperation() {}
Compartir Pointcut
Se pueden usar unos pointcuts declarados en un
aspecto en otro aspecto, usando el mismo tipo de
visibilidad que para los mtodos de java.
Los pointcuts declarados con anotaciones, se
pueden usar en configuraciones XML.

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}

@Pointcut("anyPublicOperation() && inTrading()")


public void tradingOperation() {}
Declarar Consejos (Advice)
@Before
@AfterReturning
@AfterThrowing
@After
@Around
@Before
Anotacin de mtodo que establece un consejo
antes de la ejecucin del metodo destino.
@Aspect
public class BeforeExample {

@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}

@Aspect
public class BeforeExample {

@Before("execution(* com.xyz.myapp.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
@AfterReturning
Anotacin de mtodo que establece un consejo
despus de haberse ejecutado el punto de cruce.
Se puede usar el argumento returning para tener
una referencia al objeto devuelto.

@Aspect
public class AfterReturningExample {

@AfterReturning(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
returning="retVal")
public void doAccessCheck(Object retVal) {
// ...
}
}
@AfterThrowing
Anotacin de mtodo que establece un consejo
despus de haberse ejecutado el punto de
cruce (y haber lanzado una excepcin).
Se puede usar el argumento throwing para
tener una referencia a la excepcin lanzada.
@Aspect
public class AfterThrowingExample {

@AfterThrowing(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
throwing="ex")
public void doRecoveryActions(DataAccessException ex) {
// ...
}
}
@After
Anotacin de mtodo que establece un consejo
despus de haberse ejecutado el punto de cruce.
Normalmente se usa para limpiar recursos.

@Aspect
public class AfterFinallyExample {

@After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doReleaseLock() {
// ...
}
}
@Around
Anotacin de mtodo que establece un consejo alrededor de su
ejecucin.
Se puede realizar trabajo tanto antes como despus de la ejecucin y
permite determinar cuando, como y s se ejecutar el mtodo de
cruce.
Se suele usar si se necesita guardar algn estado desde antes a
despus de la ejecucin de manera thread-safe.
El primer parmetro del mtodo de consejo debe ser de tipo
ProceedingJoinPoint.
Para llamar al procedimiento:
ProceedingJoinPoint.proceed();
ProceedingJoinPoint.proceed(Object[] args);
El valor devuelto por el mtodo proceed es el valor devuelto por el
mtodo de cruce.
El valor devuelto por el mtodo del consejo, puede suplantar el valor
devuelto por el mtodo de cruce.
@Around
@Aspect
public class AroundExample {

@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}

}
Parmetros de los mtodos
Advice
El primer parmetro puede ser de tipo JoinPoint.
En el caso de Advice tipo Around el parmetro es
obligado y es de tipo ProceedingJoinPoint (que
estiende de JoinPoint).
Este objeto da acceso al mtodo JoinPoint (ver qu
metodo es, ver sus argumentos, acceder al objeto,
etc.)

Pasar argumentos
Es posible pasar los argumentos del mtodo Join
Point al mtodo advice.
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" +
"args(account,..)")
public void validateAccount(Account account) {
// ...
}

@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" +
"args(account,..)")
private void accountDataAccessOperation(Account account) {}

@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
this, target
Se pueden usar para pasar una referencia al objeto
Proxy o al objeto Target
@Before(
value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) &&
@annotation(auditable)",
argNames="bean,auditable")
public void audit(Object bean, Auditable auditable) {
AuditCode code = auditable.value();
// ... use code and bean
}
argsNames
Es necesario cuando no se compila con informacin
de depuracin.
Si no se establece y no se compila con informacin
de depuracin, spring intentar establecer dichos
parmetros por el orden de aparicin.
Si no puede lanza una excepcin
IllegalArgumentException
Orden de los advices
Si no se especifca, el orden es indefinido.
Se puede especificar de dos maneras:
Implementando la interfaz:
org.springframework.core.Ordered
con la anotacin @Order
El valor ms bajo tiene preferencia.
Dos mtodos en el mismo aspecto no se puede
especificar. Considerar juntar los dos mtodos en uno.
El aspecto de las transacciones por defecto tienen la
mnima preferencia.
Introductions
Permite que una clase implemente una interfaz que
no se le ha definido.
@DeclareParent
@Aspect
public class UsageTracking {

@DeclareParents(value="com.xzy.myapp.service.*+",
defaultImpl=DefaultUsageTracked.class)
public static UsageTracked mixin;

@Before("com.xyz.myapp.SystemArchitecture.businessService() &&" +
"this(usageTracked)")
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
}
Prctica 1
Sacr el cdigo de auditora del objeto
ProductosBOImpl e implementarlo en un aspecto.
Crear un bean que sea un aspecto de auditora.
Crear el Point Cut
Implementar el mtodo.
Prctica 2
Implementar dicho aspecto a todos los DAO.
El mensaje que se debe escribir debera contener la
clase, el mtodo, los argumentos.
Configuracin con XML
Declarar aspectos
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>

<bean id="aBean" class="...">


...
</bean>
Declarar un PointCut
<aop:config>

<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>

</aop:config>

<aop:config>

<aop:aspect id="myAspect" ref="aBean">

<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
...

</aop:aspect>

</aop:config>
Declarar Advice
<aop:aspect id="beforeExample" ref="aBean">

<aop:before
pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>

</aop:aspect>

<aop:aspect id="afterThrowingExample" ref="aBean">

<aop:after-throwing
pointcut-ref="dataAccessOperation"
throwing="dataAccessEx"
method="doRecoveryActions"/>

</aop:aspect>
Declarar Advice
<aop:aspect id="afterFinallyExample" ref="aBean">

<aop:after
pointcut-ref="dataAccessOperation"
method="doReleaseLock"/>

</aop:aspect>

<aop:aspect id="aroundExample" ref="aBean">

<aop:around
pointcut-ref="businessService"
method="doBasicProfiling"/>

</aop:aspect>
Ejemplo
<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">

<!-- this is the object that will be proxied by Spring's AOP infrastructure -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>

<!-- this is the actual advice itself -->


<bean id="profiler" class="x.y.SimpleProfiler"/>

<aop:config>
<aop:aspect ref="profiler">

<aop:pointcut id="theExecutionOfSomeFooServiceMethod"
expression="execution(* x.y.service.FooService.getFoo(String,int))
and args(name, age)"/>

<aop:around pointcut-ref="theExecutionOfSomeFooServiceMethod"
method="profile"/>

</aop:aspect>
</aop:config>
</beans>
Introductions
<aop:aspect id="usageTrackerAspect" ref="usageTracking">

<aop:declare-parents
types-matching="com.xzy.myapp.service.*+"
implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>

<aop:before
pointcut="com.xyz.myapp.SystemArchitecture.businessService()
and this(usageTracked)"
method="recordUsage"/>

</aop:aspect>
Prctica 3
Realizar con Introductions un contador de accesos a
los objetos, que luego se les pueda llamar desde el
mtodo Main al final para contar los accesos a cada
uno de los beans.
Prctica 4
Aspecto retry
Para las operaciones DAO, reintentarlo un nmero de
veces si da error.
Este nmero ser configurable en el bean.
Prctica 5
Usar con Introductions y AOP la posibilidad de
preguntarles a los beans por el nmero de accesos
que han tenido.

Anda mungkin juga menyukai