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?