The before advice is very simple, it allows adding the concern code before the joinpoints matching the pointcut.
I will now focus on the after advice which has some more options.
It can be used as:
- after( exposed information ) returning [(exposed information)]: pointcut
- after( exposed information ) throwing [(exposed information)]: pointcut
- after( exposed information ): pointcut
The first one captures when the execution flow returns from the joinpoint (possible exposing information about the returned value).
For example, given the classes:
class C{
public static void main(){
D d = new D();
int x = d.foo();
}
}
class D {
public int foo(){
return 8;
}
}
and the advice
after() returning: call(* *.foo()){
System.out.println("after foo");
}
prints the advice message once foo has returned successfully
On the other hand, the advice
after() returning(int x): call(* *.foo()){
System.out.println("after foo");
System.out.println(x);
}
also prints the returned value by foo methods of type int
The second option above (2.) captures the exception thrown, so that if we want to add some behavior only when an exception occurred within the joinpoint this kind of advice is very useful.
For example, given the following classes
class C{
public static void main(){
D d = new D();
int x = d.foo(-1);
}
}
class D {
public int foo(int i){
if (i < 0) throw new Exception("did not expect negative value");
return Math.sqrt(i);
}
}
The advice
after() throwing: call(* *.foo()){
System.out.println("exception thrown within foo");
}
captures the problematic situation and prints the message (and the exception is still thrown to the other classes.
The third option captures returning from the joinpoint either correctly or because of an exception.
To think about: How would you write an advice that when returning from foo with an exception, also prints the exception message? (before forwarding the exception to the calling methods?)
public static void main(){
D d = new D();
int x = d.foo(-1);
}
}
class D {
public int foo(int i){
if (i < 0) throw new Exception("did not expect negative value");
return Math.sqrt(i);
}
}
The advice
after() throwing: call(* *.foo()){
System.out.println("exception thrown within foo");
}
captures the problematic situation and prints the message (and the exception is still thrown to the other classes.
The third option captures returning from the joinpoint either correctly or because of an exception.
To think about: How would you write an advice that when returning from foo with an exception, also prints the exception message? (before forwarding the exception to the calling methods?)
The boy throws a rock to the sea, as sometimes methods throw exceptions...
No comments:
Post a Comment