'Is it possible to get the return value and method arguments from the same advice in Spring AOP?

Is it possible to get the return value and method arguments from the same advice in Spring AOP?

I am trying to implement some login based on return value and the method arguments.

All this info needs to be used in the advice to implement my business logic.

For example:

MyObject testMethod(String arg 1, String arg2){
    ..
    ..
    return myObject;
}

For this case I need myObject, arg1 and arg2 all.

I tried below code with two different annotations: @After and @AfterReturning as given below:

@AfterReturning(value="execution(* com.example.aop.service.TestServiceImpl.printTestData(..))", returning="test")
public void checkSomethingAfter(JoinPoint joinPoint, Test test) {
    System.out.println("------------AFTER RETURNING-----------");
    System.out.println("After execution - 111 " + joinPoint.getArgs());
    System.out.println("After execution - test: " + test);
    System.out.println("-------------------------------------");
}

// @After(value = "execution(* com.example.aop.service.TestServiceImpl.printTestData(..)) and args()")
    @After(value = "execution(* com.example.aop.service.TestServiceImpl.printTestData(..)) && args(id)")
    public void afterAdvice(JoinPoint joinPoint, int id) {
        System.out.println("After method:" + joinPoint.getSignature());
        System.out.println("Creating Test with id - " + id);
    }

The problem is, I get the arguments in @After and return value in @Afterreturning. My requirement is to get both the return value and arguments in a one method at the same time.

How can I do this?



Solution 1:[1]

That is indeed possible. You need the @Around advice and read the arguments from the ProceedingJoinPoint.


 @Around("execution(* com.example.MyClass.testMethod(..))")
 public Object testAop(ProceedingJoinPoint pjp) throws Throwable {
    Object[] arguments = pjp.getArgs();
    Object result = pjp.proceed();
    // Do logic based on arguments + return value

    return result;
}

I do feel the implementation might become a bit sketchy so if it's not a real cross-cutting concern then perhaps it is best to write your own delegate around the method.

Solution 2:[2]

It is possible to do using @AfterReturning annotation too. Here is an example.

Assume we have this method in com.test.TestService class:

public Object test(String arg1, Integer arg2) { ... }

Then your advice method will look like this:

@AfterReturning(
        pointcut="execution(* com.test.TestService.test(..)) && args(arg1,arg2)",
        argNames="arg1,arg2,returnedValue",
        returning="returnedValue")
public void logAfterTest(String arg1, Integer arg2, Object returnedValue) {
    // some logic
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 velika12