Advice defines pieces of aspect implementation that execute at well-defined points in the execution of the program. Those points can be given either by named pointcuts (like the ones you've seen above) or by anonymous pointcuts. Here is an example of an advice on a named pointcut:
pointcut setter(Point p1, int newval): target(p1) && args(newval) (call(void setX(int) || call(void setY(int))); before(Point p1, int newval): setter(p1, newval) { System.out.println("About to set something in " + p1 + " to the new value " + newval); }
And here is exactly the same example, but using an anonymous pointcut:
before(Point p1, int newval): target(p1) && args(newval) (call(void setX(int)) || call(void setY(int))) { System.out.println("About to set something in " + p1 + " to the new value " + newval); }
Here are examples of the different advice:
This before advice runs just before the join points picked out by the (anonymous) pointcut:
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { if (!p.assertX(x)) return; }
This after advice runs just after each join point picked out by the (anonymous) pointcut, regardless of whether it returns normally or throws an exception:
after(Point p, int x): target(p) && args(x) && call(void setX(int)) { if (!p.assertX(x)) throw new PostConditionViolation(); }
This after returning advice runs just after each join point picked
out by the (anonymous) pointcut, but only if it returns normally.
The return value can be accessed, and is named x
here. After the advice runs, the return value is returned:
after(Point p) returning(int x): target(p) && call(int getX()) { System.out.println("Returning int value " + x + " for p = " + p); }
This after throwing advice runs just after each join point picked out by
the (anonymous) pointcut, but only when it throws an exception of type
Exception
. Here the exception value can be accessed
with the name e
. The advice re-raises the exception
after it's done:
after() throwing(Exception e): target(Point) && call(void setX(int)) { System.out.println(e); }
This around advice traps the execution of the join point; it runs
instead of the join point. The original action
associated with the join point can be invoked through the special
proceed
call:
void around(Point p, int x): target(p) && args(x) && call(void setX(int)) { if (p.assertX(x)) proceed(p, x); p.releaseResources(); }