Search code examples
spring-mvcannotationsaspectjspring-aopauditing

Pass object between two Around functions - AOP


I am doing Auditing for my Controller, Service and Dao layer. I have three Around aspect functions for Controller, Service and Dao respectively. I use a custom annotation which if present on the Controller method will invoke an Around aspect function. Inside the annotation I set a property which I wish to pass from the Controller Around function to the Service around function inside the Aspect class.

public @interface Audit{
   String getType();
}

I will set the value of this getType from an interface.

@Around("execution(* com.abc.controller..*.*(..)) && @annotation(audit)")
public Object controllerAround(ProceedingJoinPoint pjp, Audit audit){
  //read value from getType property of Audit annotation and pass it to service around function
}

@Around("execution(* com.abc.service..*.*(..))")
public Object serviceAround(ProceedingJoinPoint pjp){
  // receive the getType property from Audit annotation and execute business logic
}

How can I pass an object between two Around functions?


Solution

  • Aspects are, by default, singleton objects. However, there are different instantiation models, which could be useful in use cases like yours. Using a percflow(pointcut) instantiation model, you could store the value of the annotation in your controller around advice and retrieve it in your service around advice. The following is just an example on how it would look like:

    @Aspect("percflow(controllerPointcut())")
    public class Aspect39653654 {
    
        private Audit currentAuditValue;
    
        @Pointcut("execution(* com.abc.controller..*.*(..))")
        private void controllerPointcut() {}
    
        @Around("controllerPointcut() && @annotation(audit)")
        public Object controllerAround(ProceedingJoinPoint pjp, Audit audit) throws Throwable {
            Audit previousAuditValue = this.currentAuditValue;
            this.currentAuditValue = audit;
            try {
                return pjp.proceed();
            } finally {
                this.currentAuditValue = previousAuditValue;
            }
        }
    
        @Around("execution(* com.abc.service..*.*(..))")
        public Object serviceAround(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("current audit value=" + currentAuditValue);
            return pjp.proceed();
        }
    
    }