1

1) Is it possible to intercept executions (or perhaps calls) towards (from outside to inside) a set of classes (or perhaps a package, but not sub-packages) and outward calls (from those classes to outside that group of classes), but not "internal" executions/calls (from any class of that group to any class of that same group) using only pointcut definitions (i.e. not extra Java code inside advices)? 2) Is that possible to specify that group into an external file to be loaded at runtime (Load Time Weaving)?

What I want is to write a tool to apply a given aspect at runtime, but where the developer can specify the set of classes at JVM startup (command line or text file).

I have managed to implement point 1 with extra Java reflection code in the advices, but it's not ideal (slow), and I'm not sure I can load the class/package names from an external file and have them applied by AspectJ:

private static final String PACKAGE_REGEX = "com.advisethispackage..*";
private static final String BEFORE_EXECUTION_AND_NEW_INVOCATION_FILTER = "((execution(* *(..))) || (execution(*.new(..)))) && within(" + PACKAGE_REGEX + ")";
private static final String CALL_INVOCATION_FILTER = "((call(* *(..))) || (call(*.new(..)))) && within(" + PACKAGE_REGEX + ")";

I have tried using withincode (which I haven't really understood, apparently), or exclude call this way...

private static final String CALL_INVOCATION_FILTER = "((call(* *(..))) || (call(*.new(..)))) && (!call(* " + WITHIN_REGEX + "(..))) && (!call(" + WITHIN_REGEX + ".new(..))) && within(" + WITHIN_REGEX + ")";

...but it failed to excluded some same-class calls. Any ideas?

My aop.xml file looks like this:

<aspectj>
  <aspects>
    <aspect name="org.my.aspects.RecordingAspect"/>
    <include within="org..*"/>
  </aspects>

  <weaver options="-verbose -debug -showWeaveInfo">
    <include within="com.advisethispackage..*"/>
    <include within="org.my.aspects..*"/>
  </weaver>
</aspectj>

I'm quite new to AOP and only know AspectJ, and only used annotations, not the AspectJ compiler or AJDT. I'm using aspectj-1.8.6 with Java 8.


Example: I have 4 classes (A, B, C, D). A invokes a method on B, with invokes C, which invokes D. B and C are the classes I want to advise (com.advisethispackage.B, com.advisethispackage.C) but A and D are not (com.dontadvisethispackage.A, com.dontadvisethispackage.D). My RecordingAspect advices just print out "Invoked method on class 'X'" or "Invoking method from class 'X' to class 'Y'".

When recording, I want to output to be:

Invoked method on class 'B'
Invoking method from class 'C' to class 'D'

Nothing else. I'm also recording the "after" moments, which would print...

Returning from invocation of method on class 'D' called by class 'C'
Returning from invocation of method on class 'B'

...but I suppose the pointcut definition should be the same.

Thanks

tkruse
  • 10,222
  • 7
  • 53
  • 80
Marco
  • 111
  • 2
  • 8

1 Answers1

0

Don't know if you've already found this, but here are the two pointcut I fiddled to matche your case (using AspectJ annotations)

@Pointcut("call(* com.advisethispackage..*.*(..)) && !withincode(* com.advisethispackage..*.*(..))")
public void callFromOutsideToInside() {}

@Before("call(* (!com.advisethispackage..*).*(..)) && withincode(* com.advisethispackage..*.*(..))")
public void callFromInsideToOutside() {}

And if you want to also match constructors :

@Pointcut("call(com.advisethispackage..*.new(..)) && !withincode(* com.advisethispackage..*.*(..))")
public void callFromOutsideToInside() {}

@Before("call((!com.advisethispackage..*).new(..)) && withincode(* com.advisethispackage..*.*(..))")
public void callFromInsideToOutside() {}
XGouchet
  • 10,002
  • 10
  • 48
  • 83