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?)
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("execution(public * *(..))")
private void anyPublicOperation() {}
@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}
@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>
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
</aop:config>
<aop:config>
<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: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: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"/>
<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.