> ‘cflow’ might have performance problems. Is that true?
Not really, certainly no worse than if you did it by hand. There is no special magic here. Consider this point cut:
execution(* foo(..)) && cflow(execution(* bar(..))
the woven code would look like this (the ajc$ related code is created by the weaving process)
...
public void bar() {
ajc$threadlocalcounter++;
try {
foo();
} finally {
ajc$threadlocalcounter--;
}
}
...
public void foo() {
if (ajc$threadlocalcounter>0) {
ajc$beforeAdvice();
}
...
}
An if() test on the existence of an annotation would be tricky to craft (if you are thinking of an if() point cut component). If you are thinking of an if() test at the start of your advice then the code to determine the caller and dig around for its annotation would be a nasty performance problem.
> don’t you think that your argument about mixing the test conditions with 'production’ also applies here in this solution?
Yes it does.
Just brainstorming, but I wonder, if you had your advice call out to a delegate method
before(...): thisthing() {
doit(...)
}
then when running your tests use LTW to add an extra aspect that is only present when running the tests.
aspect ForTesting {
void around(): execution(* doit(..)) {
// do not proceed
}
}
This would make the doit method a no-op when run with tests.
Simpler than that perhaps, you could have your advice forward to different implementations of an interface depending on whether it is running within tests:
// my silly authentication aspect
aspect Authentication {
public static Authenticator authenticator;
public Authentication() {
this.authenticator = new Authenticator();
}
before(...): thisthing() {
authenticator.doit();
}
}
and then in your tests:
Authentication.authenticator = new MyDummyAuthenicator();
Where the dummy one has no-ops for doit
just some thoughts,
Andy