Reputation: 6440
I'm currently going through AspectJ's documentation, and I don't quite get their point on Pointcut composition. In particular, I don't understand what cFlow(P && Q)
does, when advice with that pointcut would get executed.
A PowerPoint presentation (for a course at the university of Utrecht) I found explains
cflow is the collection of join points flowing from the argument pointcut. This means that cflow(P) && cflow(Q) is the intersection of the two collections, while cflow(P && Q) means that you first combine the pointcuts P and Q, and all the join points flowing from that are in this collection.
They go on to list all join points for cFlow(P) && cFlow(Q)
(pointcut flowPAndflowQ() : cflow(execution(* Example.P(..))) && cflow(execution(* Example.Q(..))) && within(Example);
), and to me it looks like an intersection of all the control flow points of the individual statements - P ∩ Q, if you will (just like they said):
Flow from P - execution(void Example.P())
Flow from P - call(void Example.Q())
Flow from P - execution(void Example.Q())
Flow from Q - execution(void Example.Q())
Flow from P && flow from Q - execution(void Example.Q())
(Their example is like the one in the AspectJ docs, except for the lacking println() statement.)
What I (still) don't understand, is what cFlow(P && Q)
would do.
Does it mean "get all join points that are in P, then add all join points that are in Q, then match on anything that flows from any of them"? If so, I don't get the println() statement for the AspectJ example: System.out.println("should not occur");
Surely, if I add all flow points in P and Q (i.e. P + Q
), that should be the superset (union) to P ∩ Q, P ∪ Q?
Or does it mean "get all join points in P that are also in Q", i.e.
all flow points within X()
below?
public void P() { X(); }
public void Q() { X(); }
public void X() { /* all that is in the body of X() */ }
Or can it just never occour, as AspectJ's example states? (Why?)
I'd really appreciate if someone could shed some light. :)
Upvotes: 4
Views: 1141
Reputation: 3755
Does it mean "get all join points that are in P, then add all join points that are in Q, then match on anything that flows from any of them"?
No, it means get all join points that are in P and in Q so it's intersection.
Or does it mean "get all join points in P that are also in Q", i.e. all flow points within X() below?
Yes for "get all join points in P that are also in Q" and no for the remaining part. The reason is pointcut P defines a single join point: execution(void Example.P()), and pointcut Q defines a single join point: execution(void Example.Q()). Because these join points are different the intersection for them is an empty set. cflow taken from an empty set is an empty set too. That's why in AspectJ documentation this pointcut is marked with "should not occur".
Hope this helps!
This is a misleading quote from the Power Point presentation:
cflow(P && Q) means that you first combine the pointcuts P and Q, and all the join points flowing from that are in this collection
The word "combine" should be replaced with "intersect".
I created a simple example on Github that replicates the example from the PowerPoint presentation: https://github.com/medvedev1088/aspectj-cflow-composition-example
public class Example {
public void P() {
Q();
}
public void Q() {
}
public static void main(String[] args) {
new Example().P();
}
}
If you run it the output should be like this:
pointcut: P join point: execution(Example.P())
pointcut: flowP join point: execution(Example.P())
pointcut: flowP join point: call(Example.Q())
pointcut: Q join point: execution(Example.Q())
pointcut: flowP join point: execution(Example.Q())
pointcut: flowQ join point: execution(Example.Q())
pointcut: flowPAndflowQ join point: execution(Example.Q())
What this shows is that there are only 3 join points:
A: execution(Example.P())
B: call(Example.Q())
C: execution(Example.Q())
Pointcuts:
pointcut P includes only A
pointcut Q includes only C
pointcut flowP includes A, B and C
pointcut flowQ includes only C
pointcut flowPAndflowQ includes only C
We can see now that P && Q is an empty set while flowP && flowQ includes C.
I also included additional pointcut: cflow(P() && publicMethods()) (the advice for this pointcut is commented out in the code). publicMethods() is execution(public * *(..)). Unlike cflow(P() && Q()) it doesn't result in empty set.
Upvotes: 1