Loading

Advice in AOP

  • It allows you to define cross-cutting concerns separately from the main application logic.
  • It helps developers add external functionality like logging, security etc. without modifying the code.
  • Advice is the method or block of codes that are executed at a particular point at the execution of a program.
  • It is associated with the joinpoint where the advice will be executed.

Types of Advice

There are five types of Advice in AOP:

1. Before Advice: It is executed before the advised method or join point and is commonly used for tasks like logging, security checks, or input validation before the main logic.

Example:

package com.aop.aopexample.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {

    @Before("execution(* com.aop.aopexample.service.MyService.*(..))")
    public void beforeAdvice() {
       System.out.println("Before Advice Executed!!");
    }
}

Output:

Before Advice Executed!!
Inside doSomethingMethod!!

2. After Returning Advice: It is executed after the advised method successfully returns a result and is used for tasks like logging the result, data transformation, or cleanup operations.

Example:

package com.aop.aopexample.aspect;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;


@Aspect
public class LoggingAspect {


    @AfterReturning(pointcut = "execution(* com.aop.aopexample.service.MyService.*(..))", returning = "result")
    public void afterReturningAdvice(Object result) {
    	System.out.println("AfterReturning Advice Executed!!");
    }
}

Output:

Inside doSomethingMethod!!
AfterReturning Advice Executed!!

3. After Throwing Advice: It is executed after the advised method throws an exception, It is typically used for exception handling and cleanup operations.

Example: 

package com.aop.aopexample.aspect;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;


@Aspect
public class LoggingAspect {


   @AfterThrowing(pointcut = "execution(* com.aop.aopexample.service.MyService.*(..))", throwing = "exception")
    public void afterThrowingAdvice(Exception exception) {
    	System.out.println("AfterThrowing Advice Executed!!");
    }
}

Output:

Exception in thread "main" AfterThrowing Advice Executed!!
java.lang.ArithmeticException: / by zero

4. After (Finally) Advice: It is executed regardless of whether the advised method completes successfully or throws an exception. It is useful for tasks like resource cleanup (e.g., closing database connections).

Example: 

 package com.aop.aopexample.aspect;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;


@Aspect
public class LoggingAspect {


    @After("execution(* com.aop.aopexample.service.MyService.*(..))")
    public void afterAdvice() {
    	System.out.println("After Advice Executed!!");
    }
}

Output:

Inside doSomethingMethod!!
After Advice Executed!!

5. Around Advice: It is the most powerful and flexible type of advice and wraps around the advised method, allowing you to control its execution completely. You can modify input, and output, or even bypass the advised method entirely. It is commonly used for profiling, caching, and custom transaction management.


Example: 

package com.aop.aopexample.aspect;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.ProceedingJoinPoint;


@Aspect
public class LoggingAspect {


   @Around("execution(* com.aop.aopexample.service.MyService.*(..))")
    public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // Proceed with the original method
        long endTime = System.currentTimeMillis();

        String methodName = joinPoint.getSignature().toShortString();
        long executionTime = endTime - startTime;

        System.out.println(methodName + " executed in " + executionTime + " ms");
        return result; // Return the original method's result
    }
}

Output:

Inside doSomething Method!!
MyService.doSomething() executed in 6 ms