Search code examples
javaaopaspectj

How do I access private fields with AspectJ?


I am investigating AspectJ and its many uses and have discovered mixins.

I can find many examples employing pure AspectJ .aj aspects however I need to use only @AspectJ annotations.

What I am trying to achieve is the following:-

I have a class that I cannot amend, it has a private class variable that I need to interrogate after a particular class method has completed execution. This class does not have getter or setter methods associated with this private class variable.

public final class CannotAmend {

    private Uri privateUri;

    public final void methodOne(){}

    public final void methodTwo(){}

    public final void methodThree(){

        privateUri = "something";   

    }
}

I require an aspect/mixin that can capture @After methodThree() and allow me to see the value set in privateUri.

Is this possible to achieve?

With @AspectJ annotations?

Where can I discover documentation/tutorial/examples of how to achieve this?


Solution

  • Within an aspect you can access the private field using the reflection API.

    In the aspect you need two things:

    • A pointcut to define methods on which the aspect matches.
    • And a method annotated with @After containing logic that's executed after a method matched by the pointcut returns.

    @Aspect
    public class MyAspect {
    
        @Pointcut("execution(* CannotAmend.methodThree(..))")
        public void methodThreePointcut(){
        }
    
        @After("methodThreePointcut()")
        public void afterMethod(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {
            Object instance = joinPoint.getThis();
    
            Field privateUriField = instance.getClass().getDeclaredField("privateUri");
            privateUriField.setAccessible(true);
    
            String privateUri = (String) privateUriField.get(instance);
            System.out.println(privateUri); // prints "something"
        }
    }
    

    On a side note, using String constants to access a private field is not a clean solution. If sometime in the future the name of the variable changes or if it's removed, the aspect will break.