Question

I have a CachingAspect which performs some simple caching on properly annotated methods using an around advice. Now, what I want to do is to trace the caching and the around advice in particular.

So far I'm able to intercept method calls within the around advice but not the advice itself. Ultimately, I would want to get the signature of the method the around advice is advising. Is it possible?

Thanks in advance!

Was it helpful?

Solution

What do you mean by

[adviceexecution pointcut] is not working for me

For me it works just fine, like so:

public aspect MetaAspect {
    before() : within(DummyAspect) && adviceexecution() {
        System.out.println("MetaAspect: " + thisJoinPointStaticPart.getSignature());
        for (Object arg : thisJoinPoint.getArgs())
            System.out.println("    " + arg);
    }
}

From that point, looking at the signatures printed, you should be able to further refine which advice to pick from DummyAspect if there is more than one and they have different signatures.


Update:

Okay, you have edited your question and stated that what you need to determine is not just adviceexecution() but also the intercepted method's signature. There is no 100% solution for that, but if you make sure your intercepted advice somehow refers to methods of thisJoinPointStaticPart, an instance of JoinPoint.StaticPart will be added to the advice's own signature and can be accessed from your meta aspect. Here is a complete code sample:

Driver application:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        Application application = new Application();
        application.writeProperty("fullName", "John Doe");
        application.readProperty("firstName");
        application.doSomething(11);
    }

    public void writeProperty(String name, String value) {}
    public String readProperty(String name) { return "foo"; }
    public void doSomething(int number) {}
}

Caching aspect:

package de.scrum_master.aspect;

public aspect CachingAspect {
    pointcut readMethods(String propertyName) :
        execution(* *.read*(String)) && args(propertyName);

    before(String propertyName) : readMethods(propertyName) {
        System.out.println(
            "[CachingAspect] Read method called for property '" + propertyName + "'"
        );
    }

    Object around(String propertyName) : readMethods(propertyName) {
        System.out.println(
            "[CachingAspect] Caching property '" + propertyName +
            "' in method " + thisJoinPointStaticPart.getSignature()
        );
        return proceed(propertyName);
    }
}

As you can see, there are two advice in this aspect. The first one does not access any join point members, the second one does. I.e. we will be able to find out the second one's target signature only in our meta aspect.

Meta aspect:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint.StaticPart;

public aspect AdviceInterceptor {
    before() : within(CachingAspect) && adviceexecution() {
        System.out.println("[AdviceInterceptor] Intercepting " + thisJoinPointStaticPart);
        boolean foundSignature = false;
        for (Object arg : thisJoinPoint.getArgs()) {
            if (arg instanceof StaticPart) {
                foundSignature = true;
                StaticPart jpStaticPart = (StaticPart) arg;
                System.out.println("[AdviceInterceptor] Target method = " + jpStaticPart.getSignature());
                break;
            }
        }
        if (!foundSignature)
            System.out.println("[AdviceInterceptor] Target method cannot be determined from advice signature");
    }
}

The meta advice iterates over its parameters in order to find a JoinPoint.StaticPart type parameter. If it finds one, it prints its target signature, otherwise it prints a failure note after the loop.

Sample output:

[AdviceInterceptor] Intercepting adviceexecution(void de.scrum_master.aspect.CachingAspect.before(String))
[AdviceInterceptor] Target method cannot be determined from advice signature
[CachingAspect] Read method called for property 'firstName'
[AdviceInterceptor] Intercepting adviceexecution(Object de.scrum_master.aspect.CachingAspect.around(String, AroundClosure, JoinPoint.StaticPart))
[AdviceInterceptor] Target method = String de.scrum_master.app.Application.readProperty(String)
[CachingAspect] Caching property 'firstName' in method String de.scrum_master.app.Application.readProperty(String)

OTHER TIPS

You can use the thisJoinPoint.getSignature() inside the advice to get the method signature like this:

pointcut tolog1() : execution(* Activity+.*(..)) ;
before() : tolog1() {
    String method = thisJoinPoint.getSignature().toShortString();

    Log.d(ATAG, "=========== entering " + method+", parms="+Arrays.toString(thisJoinPoint.getArgs()));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top