package org.bk.inventory.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Aspect
public class AuditAspect {
private static Logger logger = LoggerFactory.getLogger(AuditAspect.class);
@Pointcut("execution(* org.bk.inventory.service.*.*(..))")
public void serviceMethods(){
//
}
@Before("serviceMethods()")
public void beforeMethod() {
logger.info("before method");
}
@Around("serviceMethods()")
public Object aroundMethod(ProceedingJoinPoint joinpoint) {
try {
long start = System.nanoTime();
Object result = joinpoint.proceed();
long end = System.nanoTime();
logger.info(String.format("%s took %d ns", joinpoint.getSignature(), (end - start)));
return result;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@After("serviceMethods()")
public void afterMethod() {
logger.info("after method");
}
}
The @Aspect annotation on the class identifies it as an aspect definition. It starts by defining the pointcuts:
@Pointcut("execution(* org.bk.inventory.service.*.*(..))")
public void serviceMethods(){}
The above basically identifies all the methods of all types in org.bk.inventory.service package, this pointcut is identified by the name of the method on which the annotation is placed - in this case "serviceMethods". Next, the advice is defined using the @Before(serviceMethods()), @After(serviceMethods()) and @Around(serviceMethods()) annotation and the specifics of what needs to happen is the body of the methods with those annotations. Spring AOP natively understands the @AspectJ annotations, if this Aspect is defined as a bean: <bean id="auditAspect" class="org.bk.inventory.aspect.AuditAspect" />Spring would create a dynamic proxy to apply the advice on all the target beans identified as part of the pointcut notation.
Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example