Reputation: 53
I'm developing an Advice and I want to make it advise only on field sets in specific methods.
I tried cflow(pointcutForSpecificMethod()) && set(* *)
pointcut expression but it picks field sets in other methods under control flow of specific methods.
Any idea?
Upvotes: 0
Views: 148
Reputation: 67317
This is not possible directly with an exact pointcut expression, but you can use if()
pointcuts to dynamically determine from the stack trace or - like in this case - from the enclosing join point static part exposed by AspectJ - what the executing method is. Here is a little example and an aspect in two variants: native syntax (my preference, more elegant and less boilerplate) and annotation-style syntax:
package de.scrum_master.app;
public class Application {
private int field = 0;
public static void main(String[] args) {
Application app = new Application();
app.foo(11);
app.bar(22);
}
public void foo(int i) {
field = i;
bar(2 * i);
}
void bar(int i) {
field = i;
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
public aspect MyAspectNative {
pointcut pointcutForSpecificMethod() : execution(* foo(*));
public static boolean executingMethodMatches(JoinPoint.StaticPart staticPart) {
return staticPart.getSignature().toLongString().contains("de.scrum_master.app.Application.foo(int)");
}
before() :
cflow(pointcutForSpecificMethod()) && set(* *) &&
if(executingMethodMatches(thisEnclosingJoinPointStaticPart))
{
System.out.println(thisEnclosingJoinPointStaticPart);
System.out.println(thisJoinPoint);
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("execution(* foo(*))")
private static void pointcutForSpecificMethod() {}
@Pointcut("if()")
public static boolean executingMethodMatches(JoinPoint.EnclosingStaticPart staticPart) {
return staticPart.getSignature().toLongString().contains("de.scrum_master.app.Application.foo(int)");
}
@Before(
"cflow(pointcutForSpecificMethod()) && set(* *) && " +
"executingMethodMatches(thisEnclosingJoinPointStaticPart)"
)
public void beforeAdvice(JoinPoint thisJoinPoint, JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart)
{
System.out.println(thisEnclosingJoinPointStaticPart);
System.out.println(thisJoinPoint);
}
}
I tried to keep the two aspects as similar as possible structurally. No matter which aspect syntax variant you choose, the output will be:
execution(void de.scrum_master.app.Application.foo(int))
set(int de.scrum_master.app.Application.field)
Upvotes: 1