javaaspectjpointcutpointcuts

AspectJ: Intercept return result of method inside another method


I need help to write some Aspectj advice on this particular case:

Suppose we have this class:

package org.group;

public class Person {

   public void method1(String id, String number) {
       //some code
       List<String> list = getList(number);
       //some code
   }

   public List<String> getList(String number) {
       return Arrays.asList(number);
   }

}

I want to create an Aspectj advice into method1 to get the result of getList. I try this:

@Pointcut("execution(* org.group.Person.getList(..))")
public void methodGetList() {

}

@AfterReturning(pointcut = "methodGetList()", returning = "result")
public void afterMethodGetList(JoinPoint joinPoint, List<String> result) {
    System.out.println("I can see the list result: " + result.toString());
}

This advice works on all executions of getList method, but what I want exactly, is to get the result inside the method1 call to get an information with the method1's id , for example like this:


'I can see the list result [4] for the person with id : XXX'

Thank you for your help.


Solution

  • You need to limit your pointcut to the executions within the control flow - cflow() - of the calling method and also bind the calling method's parameter of interest via args().

    Application:

    package org.group;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class Person {
      public void method1(String id, String number) {
        // some code
        List<String> list = getList(number);
        // some code
      }
    
      public List<String> getList(String number) {
        return Arrays.asList(number);
      }
    
      public static void main(String[] args) {
        // Should not be intercepted
        new Person().getList("22");
        // Should be intercepted
        new Person().method1("John Doe", "11");
      }
    }
    

    Aspect:

    package de.scrum_master.aspect;
    
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class MyAspect {
      @Pointcut("execution(* org.group.Person.getList(..))")
      public void methodGetList() {}
    
      @Pointcut("execution(* org.group.Person.method1(..)) && args(id, *)")
      public void methodMethod1(String id) {}
    
      @AfterReturning(
        pointcut = "methodGetList() && cflow(methodMethod1(id))",
        returning = "result"
      )
      public void afterMethodGetList(JoinPoint joinPoint, String id, List<String> result) {
        System.out.println(
          "I can see the list result " + result +
          " for the person with id " + id
        );
      }
    }
    

    Console log:

    I can see the list result [11] for the person with id John Doe