Skip to content
Advertisement

how to pick set joinpoints in specific methods in AspectJ

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?

Advertisement

Answer

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)
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement