I am new to Aspect oriented programming. In this context, I have been going through a few designators, in which I found two designators "within" and "withincode". I could not understand their difference. Can anyone please explain with a simple example ?
Nándor's answer is correct, you should accept + upvote it. I just want to add an MCVE, a simple example illustrating what he just explained so well. I am doing this for the benefit of other users who may find this question in the future in order to help them understand better what was described here theoretically.
Driver application:
package de.scrum_master.app;
public class Application {
private int id;
private String name;
public Application(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Application[id=" + id + ", name=" + name + "]";
}
public void printName() {
System.out.println(this);
}
public static void main(String[] args) {
new Application(11, "My application").printName();
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.Application;
public aspect WithinVsWithincodeAspect {
before() : withincode(* Application.printName()) {
System.out.println("[withincode] " + thisJoinPoint);
}
before() : within(Application) {
System.out.println("[within] " + thisJoinPoint);
}
}
Console log:
[within] staticinitialization(de.scrum_master.app.Application.<clinit>)
[within] execution(void de.scrum_master.app.Application.main(String[]))
[within] call(de.scrum_master.app.Application(int, String))
[within] preinitialization(de.scrum_master.app.Application(int, String))
[within] initialization(de.scrum_master.app.Application(int, String))
[within] execution(de.scrum_master.app.Application(int, String))
[within] set(int de.scrum_master.app.Application.id)
[within] set(String de.scrum_master.app.Application.name)
[within] call(void de.scrum_master.app.Application.printName())
[within] execution(void de.scrum_master.app.Application.printName())
[withincode] get(PrintStream java.lang.System.out)
[within] get(PrintStream java.lang.System.out)
[withincode] call(void java.io.PrintStream.println(Object))
[within] call(void java.io.PrintStream.println(Object))
[within] execution(String de.scrum_master.app.Application.toString())
[within] call(java.lang.StringBuilder(String))
[within] get(int de.scrum_master.app.Application.id)
[within] call(StringBuilder java.lang.StringBuilder.append(int))
[within] call(StringBuilder java.lang.StringBuilder.append(String))
[within] get(String de.scrum_master.app.Application.name)
[within] call(StringBuilder java.lang.StringBuilder.append(String))
[within] call(StringBuilder java.lang.StringBuilder.append(String))
[within] call(String java.lang.StringBuilder.toString())
Application[id=11, name=My application]
As you can see, within()
matches a super-set of joinpoints compared to withincode()
. Of course you can combine both pointcuts with others via &&
in order to narrow down the set of matched joinpoints even further or expand it via ||
. Exclusion via !
is also possible, of course.
Please further note that withincode()
matches what happens inside the target method but not the method execution itself. In this regard it is similar to cflowbelow()
but it would not match anything outside of that method called from there as cflow()
and cflowbelow()
do.