Aspect Oriented Programming (AOP)
Introduction

Spring AOP allows developers to separate the implementation of these cross-cutting concerns (applying to different classes) from the business logic of the application, making the code more modular and easier to understand.
If we call want to add some common logic, such as logging, security to the method, it is not ideal to add it directly into method, as there are much methods in the application
Moreover, it is very time-wasting to update the method one by one if we need to update the common logic
So that, we separate the common logic into aspect class and define which method which timing should apply
We can modify the configuration by updating few lines easily instead of modifying the method one by one when updated the common logic
Terminology
Advice: the action that perform before getting the result from method
Point Cut: the expression that declare the condition of triggering the advice
Join Point: To get back the method name of method and the relative parameters
Order: To declare which aspect java class will be executed first
Point Cut
The expression format: Modifier(Optional) , Return type , Path of class, method(params)
(*) means any, method name(..) means any type and number of params
@Aspect
public class AopExpression {
@Pointcut("execution(public void com.luv2code.dao.*.add*(..))")
public void forDaoPackageAdd(){}
@Pointcut("execution(* com.luv2code.dao.*.get*())")
public void forDaoPackageGet(){}
@Pointcut("execution(* com.luv2code.dao.*.set*(..))")
public void forDaoPackageSet(){}
@Pointcut("execution(* *(..))")
public void forAllPackageAllMethod(){}
@Pointcut("forAllPackageAllMethod() && !(forDaoPackageSet() || forDaoPackageSet() )")
public void forAllPackageAllMethodWithoutGetSet(){}
@Pointcut("execution(* com.luv2code.dao.*.find*(..))")
public void forDaoPackageFind(){}
}
Advice
There are 5 types of advice
Before: before the method is executed
After: after the method is executed
AfterReturning: after the method is executed successfully, we can obtain the result and do some stuff which can change the result
AfterThrowing: after the method is executed with exception, we can obtain the exception
Around: The advice will be executed before and after the method execution, and also can handle the exception by return the default value to the main program
@Aspect
@Component
@Order(-1)
public class myDemoLoggingAspect {
private static Logger myLogger = Logger.getLogger(myDemoLoggingAspect.class.getName());
@Around("com.luv2code.aspect.AopExpression.forDaoPackageFind()")
public Object aroundFindAccountAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
String method = proceedingJoinPoint.getSignature().toString();
Object result = null;
try {
myLogger.info(" Execute Around Method " + method);
long begin = System.currentTimeMillis();
result = proceedingJoinPoint.proceed();
long end = System.currentTimeMillis();
long duration = end - begin;
myLogger.info("Duration: " + duration);
}
catch(Exception e){
myLogger.warning(" handle the exception on around aspect");
throw e;
// List<Account> accountList = new ArrayList<>();
// accountList.add(new Account("Test","Gold"));
// result = accountList;
}
return result;
// return null;
}
@After("com.luv2code.aspect.AopExpression.forDaoPackageFind()")
public void afterFindAccountAdvice(JoinPoint joinPoint){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
myLogger.info("After Find Method Signature: " + methodSignature);
}
@AfterReturning(pointcut = "com.luv2code.aspect.AopExpression.forDaoPackageFind()", returning = "result")
public void afterReturningFindAccountAdvice(JoinPoint joinPoint, List<Account> result){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
myLogger.info("After Returning Find Method Signature: "+ methodSignature);
result.stream().forEach(eachResult -> myLogger.info(eachResult.getLevel() + " " + eachResult.getName()));
result.remove(0);
}
@AfterThrowing(pointcut = "com.luv2code.aspect.AopExpression.forDaoPackageFind()", throwing = "throwException")
public void afterThrowingFindAccountAdvice(JoinPoint joinPoint, Throwable throwException){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
myLogger.info("After Returning Find Method Signature: " + methodSignature +" And Exception is " + throwException.getMessage());
}
@Before("com.luv2code.aspect.AopExpression.forAllPackageAllMethod()")
public void performLogging(JoinPoint joinPoint){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
myLogger.info("perform Logging");
myLogger.info("Method Signature " + methodSignature);
Object [] args = joinPoint.getArgs();
Arrays.stream(args).forEach((arg)-> myLogger.info("arg: "+ arg));
}
Last updated
Was this helpful?