Introduction to Aspect-Oriented Programming Martin Giese Chalmers University of Technology Göteborg, Sweden AOP Course 2003 p.1/44
AspectJ Quick Tour AOP Course 2003 p.2/44
Reminder: Join Points A join point is a well-defined point in the execution of a program. Examples: a method/constructor call execution of a method/constructor implementation read/write access to a field. Program flow can enter and leave a join point. AOP Course 2003 p.3/44
Reminder: Pointcuts A pointcut is the static designation of some set of join points for every execution of the program. Examples: all calls to public methods of the Point class every execution of a constructor with one int argument every write access to a public field. AOP Course 2003 p.4/44
Code Example: Figure Editor Figure +makepoint(..) +makeline(..) * FigureElement +moveby(int,int) Display +update() Point +getx() +gety() +setx(int) +sety(int) +moveby(int,int) 2 Line +getp1() +getp2() +setp1(point) +setp2(point) +moveby(int,int) AOP Course 2003 p.5/44
Code Example (cont.) class Line implements FigureElement { private Point p1, p2; Point getp1() { return p1; } Point getp2() { return p2; } void setp1(point p1) { this.p1 = p1; } void setp2(point p2) { this.p2 = p2; } void moveby(int dx, int dy) { p1.moveby(dx,dy); p2.moveby(dx,dy); } } class Point implements FigureElement { private int x = 0, y = 0; int getx() { return x; } int gety() { return y; } void setx(int x) { this.x = x; } void sety(int y) { this.y = y; } void moveby(int dx, int dy) { x += dx; y += dy; } } AOP Course 2003 p.6/44
Pointcuts in AspectJ Primitive pointcuts: call(void Point.setX(int)) each join point that is a call to a method that has the signature void Point.setX(int) Also for interface signatures: call(void FigureElement.moveBy(int,int)) Each call to the moveby(int,int) method in a class that implements FigureElement More later... AOP Course 2003 p.7/44
Composition of Pointcuts Pointcuts can be joined using boolean operators &&,,!. call(void Point.setX(int)) call(void Point.setY(int)) calls to the setx and sety methods of Point. Question: what does this select? call(void Line.setP1(Point)) && call(void Line.setP2(Point)) AOP Course 2003 p.8/44
Join points from many types Join points from different types possible: call(void FigureElement.moveBy(int,int)) call(void Point.setX(int)) call(void Point.setY(int)) call(void Line.setP1(Point)) call(void Line.setP2(Point)) Any call to a state-changing method in the given FigureElement classes AOP Course 2003 p.9/44
Named Pointcuts Pointcuts can be declared to give them a name: pointcut statechange() : call(void FigureElement.moveBy(int,int)) call(void Point.setX(int)) call(void Point.setY(int)) call(void Line.setP1(Point)) call(void Line.setP2(Point)); Analogous to method declaration or typedef in C. After declaration, statechange() can be used wherever a pointcut is expected. AOP Course 2003 p.10/44
Wildcards Method signatures can contain wildcards: call(void java.io.printstream.println(*)) any PrintStream method named println returning void and taking exactly one argument of any type. call(public * Figure.*(..)) any public method in Figure. call(public * Line.set*(..)) any method in Line with a name starting with set. AOP Course 2003 p.11/44
Example The pointcut from before, using wildcards: pointcut statechange() : call(void FigureElement.moveBy(int,int)) call(* Point.set*(*)) call(* Line.set*(*)); AOP Course 2003 p.12/44
Advice in AspectJ Advice can be attached to join points: before(): statechange() { System.out.println("about to change state"); } after() returning: statechange() { } System.out.println("just successfully changed state"); AOP Course 2003 p.13/44
Aspects in AspectJ public aspect DisplayUpdating { pointcut statechange() : call(void FigureElement.moveBy(int,int)) call(* Point.set*(*)) call(* Line.set*(*)); after() returning : statechange() { Display.update(); } } After every state changing call, update the display. AOP Course 2003 p.14/44
Compilation No partial compilation in AspectJ! Always provide all class and aspect source files. ajc Main.java Display.java Figure.java FigureElement.java \ Line.java Point.java DisplayUpdating.java or ajc -argfile files.lst run using: java Main AOP Course 2003 p.15/44
AspectJ Details AOP Course 2003 p.16/44
Type Patterns Used to denote a set of types. int Line * java.util.map* java..*factory* java.io.outputstream+ Foo+ &&!Foo Foo+ &&!(java..bar*[]) AOP Course 2003 p.17/44
Method Patterns Used to denote a set of methods in one or more classes. Method declaration: public final void write(int x) throws IOException Method pattern: public final void Writer.write(int) throws IOException Wildcards possible everywhere... void *.write(int) void Foo+.set*(int) AOP Course 2003 p.18/44
Method Patterns (cont.) * Foo.write(*) * Foo.write(..) * Foo.write(..,int) * *.*(..) public Foo.*(..)!public *.*(..) * *.*(..) throws java.io.ioexception * *.*(..) throws!java.io.ioexception * *.*(..) throws (!java.io.ioexception) AOP Course 2003 p.19/44
Constructor and Field Patterns Select a set of constructors: Like method patterns, with name new and no return type: Line.new(int) public *.new(..). Field Patterns: int Line.x public!final * FigureElement+.*. AOP Course 2003 p.20/44
Primitive Pointcuts call(methodpattern) call(constructorpattern) execution(methodpattern) execution(constructorpattern) get(fieldpattern) set(fieldpattern) handler(typepattern) AOP Course 2003 p.21/44
Restricting the Scope Static Scope: within(typepattern) withincode(methodpattern) withincode(constructorpattern) Dynamic Scope: cflow(pointcut) cflowbelow(pointcut) AOP Course 2003 p.22/44
Examples Match constructor calls from outside factory: call(figureelement+.new()) &&!within(figure) Match state changing calls that are not due to other state changing calls: statechange() &&!cflowbelow(statechange()) Match state changes that are not due to some method in Figure: statechange() &&!cflow(execution(* Figure.*(..))) AOP Course 2003 p.23/44
Example: cflow caller point 1 moveby a line moveby point 2 moveby AOP Course 2003 p.24/44
Pointcuts with Parameters One often needs information about the context of a join point. use pointcuts with parameters. Example: pointcut statechange(figureelement figelt) : target(figelt) && ( call(void FigureElement.moveBy(int,int)) call(* Point.set*(*)) call(* Line.set*(*)) ); after(figureelement fe) : statechange(fe) {...} AOP Course 2003 p.25/44
Parameters in pointcut declaration pointcut statechange(figureelement figelt) : target(figelt) && ( call(void FigureElement.moveBy(int,int)) call(* Point.set*(*)) call(* Line.set*(*)) ); figelt declared in header, together with name. bound by the target pointcut target alone matches any non-static call, field access, etc. if the target type matches the declared parameter type. AOP Course 2003 p.26/44
Parameters in advice declaration after(figureelement fe) : statechange(fe) {... code can use fe... } after(figureelement fe) : target(fe) &&... {... code can use fe... } fe declared in header bound by the pointcut values move from right to left over the colon. AOP Course 2003 p.27/44
Some more Pointcuts target(id) target(type) this(type or Id) args(type or Id... ) if(boolean expression) AOP Course 2003 p.28/44
Example: Diagonal Moves Define a pointcut for moves with equal dx and dy. pointcut diagmove() : call(void FigureElement.moveBy(int,int)) && args(dx,dx); AOP Course 2003 p.29/44
Example: Diagonal Moves Define a pointcut for moves with equal dx and dy. pointcut diagmove(int dx) : call(void FigureElement.moveBy(int,int)) && args(dx,dx); AOP Course 2003 p.30/44
Example: Diagonal Moves Define a pointcut for moves with equal dx and dy. pointcut diagmove(int dx,int dy) : call(void FigureElement.moveBy(int,int)) && args(dx,dy) && if(dx==dy); AOP Course 2003 p.31/44
Example: Diagonal Moves Define a pointcut for moves with equal dx and dy. pointcut diaghelp(int dx,int dy) : call(void FigureElement.moveBy(int,int)) && args(dx,dy) && if(dx==dy); pointcut diagmove(int dxy) : diaghelp(dxy,int); AOP Course 2003 p.32/44
About Conditionals AspectJ specification: The boolean expression used can only access static members, variables exposed by the enclosing pointcut or advice, (and thisjoinpoint forms). But still... static methods may be called, which may have side effects! left to right evaluation order of pointcuts. Exercise: What about join points of static functions called in if? AOP Course 2003 p.33/44
Advice in AspectJ Before advice: before(formal parameters) : Pointcut {... advice body... } The advice body gets executed every time just before the program flow enters a join point matched by the pointcut. The formal parameters receive values from the pointcut. AOP Course 2003 p.34/44
After Advice After advice: after(formal parameters) returning : Pointcut {...} The advice body gets executed every time just after the program flow exits a join point matched by the pointcut by returning normally. Capture return value: after(...) returning (int ret): Pointcut {...} AOP Course 2003 p.35/44
After Advice (cont.) Advice after throwing an exception: after(formal parameters) throwing : Pointcut {...} Capture thrown exception: after(...) throwing (Exception e): Pointcut {...} Match normal and abrupt return: after(...) : Pointcut {...} AOP Course 2003 p.36/44
Around Advice Run advice instead of original code: Type around(... ) :... {... proceed(... );... } run advice body instead of original call, field access, method body, etc. use proceed to use the original join point, if needed. AOP Course 2003 p.37/44
Example: Caching Cache values from an expensive function call. int around(int x) : call(int Expensive.f(int)) && args(x) { if (cache.contains(x)) { return cache.get(x); } else { int result = proceed(x); cache.put(x,result); return result; } } AOP Course 2003 p.38/44
thisjoinpoint For tracing or logging join points, matched methods might have very different signatures. difficult to pass all useful information through parameters. Special variable thisjoinpoint available in advice. thisjoinpoint.tostring() thisjoinpoint.gettarget() thisjoinpoint.getargs() thisjoinpoint object expensive to construct. thisjoinpointstaticpart is statically constructed. AOP Course 2003 p.39/44
Aspects in AspectJ Similar to class declarations, but Can also contain pointcut and advice declarations, System and not user controls instantiation, (An aspect gets instantiated the first time, some advice in it needs to be executed.) Aspects can extend only abstract aspects, (They can extend classes and implement interfaces) Classes cannot extend aspects. AOP Course 2003 p.40/44
Caching Aspect package se.chalmers.cs.caching; import se.chalmers.cs.calculations.expensive; public aspect CacheExpensiveFunction { private IntegerCache cache = new IntegerCache(); } int around(int x) : call(int Expensive.f(int)) && args(x) { if (cache.contains(x)) { return cache.get(x); } else { int result = proceed(x); cache.put(x,result); return result; } } AOP Course 2003 p.41/44
Tracing Aspect (first try) package tracing; public aspect TraceAllCalls { pointcut pointstotrace() : call(* *.*(..)) ; before() : pointstotrace() { } System.err.println("Enter " + thisjoinpoint); } after() : pointstotrace() { System.err.println("Exit } " + thisjoinpoint); AOP Course 2003 p.42/44
Tracing Aspect package tracing; public aspect TraceAllCalls { pointcut pointstotrace() : call(* *.*(..)) &&!within(traceallcalls); before() : pointstotrace() { } System.err.println("Enter " + thisjoinpoint); } after() : pointstotrace() { System.err.println("Exit } " + thisjoinpoint); AOP Course 2003 p.43/44
Conclusion You should now know about... AspectJ s main kinds of primitive pointcuts named pointcuts pointcuts with parameters different kinds of advice thisjoinpoint syntax for aspects Tomorrow, you will learn about inter-type declarations and other advanced stuff. AOP Course 2003 p.44/44