650 likes | 766 Views
AspectJ™: aspect-oriented programming using Java™ technology. Gregor Kiczales University of British Columbia and AspectJ.org. my personal research goal. to enable programmers to write code that looks as much as possible like the design it implements code that “looks like the design”
E N D
AspectJ™:aspect-oriented programming usingJava™ technology Gregor KiczalesUniversity of British Columbia and AspectJ.org TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
my personal research goal • to enable programmers to write codethat looks as much as possible like thedesign it implements • code that “looks like the design” • same modularity and structure as design • intended benefits • traceability is easier • easier to debug and maintain • more fun to write TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
my history with objects • 81-84 – OO systems programming on the Lisp machine • 85-92 – Common Lisp Object System • 88-93 – metaobject protocols • 96-now – aspect-oriented programming TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
Common Lisp Object System(CLOS) • idea: integrate objects and Lisp • break OOP into constituent pieces • polymorphic dispatch generic functions • multi-methods • everything is an object • standard classes and built-in classes TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
generic function syntax the syntax of a function call is the same asthe syntax of a generic function call (car x) (get-name p1) (display item window) (display item stream) the caller can’t tell whether these are functions or generic functions TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
generic function syntax the syntax of a function call is the same asthe syntax of a generic function call (car x) (get-name p1) (display item window) (display item stream) each of these can have methods that dispatch based on the class of the arguments • increases abstraction • means implementation can change • takes “message as goal” more seriously! • enables multi-methods • (can’t add “real” multi-methods to Java) TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
CLOS was open source • PCL implementation of CLOS • portable • high-performance • written in Common Lisp • enabled users to be involved in design • all features had real user feedback before they went into the standards document TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
CLOS Metaobject Protocol • idea: everything is OO • including the programming language itself • metaobject protocol is meta-level framework • can change language semantics • programmer could change • inheritance rules • kinds of methods • object implementation structure • scope control • localized changes to specific parts of program TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
CLOS metaobject protocol apply yourself generic function draw class line doyou apply? method for line what is your inheritance? method for circle line obj (draw obj) TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
aspect-oriented programming • its hard to build with objects alone TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
will show code & language details aspect-oriented programming AspectJ™ by improving their modularity design, implementation & debugging a technical talk about howa new programming paradigm, as realized in an extension to the Java™ programming language can improve programs,and help with development this talk… a technical talk about howa new programming paradigm, as realized in an extension to the Java™ programming language can improve programs,and help with development TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
clients call server client1 Server client2 worker 2 worker 1 worker 3 consider a system like TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
clients call server client1 Server client2 worker 2 worker 1 worker 3 OOP increases modularity • the data structure used to store • the search algorithm • the marshalling TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
but… • context specific behavior here • synchronization • job logging TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
client1 Server clients call server client2 worker 2 worker 1 worker 3 but… TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
Library Document public class Library { private Hashtable docs = new Hashtable(); private Hashtable users = new Hashtable(); private Printer printer; private class TerminalInfo { Terminal terminal; Thread thread; }; TerminalInfo term; Library(Printer p) { printer = p; for (int i = 0; i < 100 ; i++) { Document doc = new Document("book" + String.valueOf(i)); docs.put(doc, "book" + String.valueOf(i)); } for (int i = 0; i < 100 ; i++) { User user = new User("user" + String.valueOf(i)); users.put(user, "user" + String.valueOf(i)); } } public Document search(Terminal t, String key) { term.terminal = t; term.thread = Thread.currentThread(); try { return (Document)docs.get(key); } catch (Exception e) { System.out.println("Search interrupted at user's request"); } return null; } public boolean print(Terminal t, Document doc) { term.terminal = t; term.thread = Thread.currentThread(); try { return printer.print(doc); } catch (Exception e) { System.out.println("Print interrupted at user's request"); printer.interruption(doc); } return false; } public String quota(Terminal t, String username) { term.terminal = t; term.thread = Thread.currentThread(); try { User user = (User)users.get(username); if (user != null) return String.valueOf(user.quota); } catch (Exception e) { System.out.println("Quota query interrupted at user's request"); } return null; } public void interruption(Terminal t) { if (t == term.terminal) { term.thread.interrupt(); } } public static void main(String[] args) { Printer printer = new Printer(); Library lib = new Library(printer); Terminal term = new Terminal(lib); } } class Document { String name; Document(String n) { name = n; } } User class User { String name; int quota; User(String n) { name = n; } } Terminal public class Terminal { private Library lib; Thread termthread; Terminal (Library l) { lib = l; } public void logon() {} public void gui() {} public Document search(String key) { try { return lib.search(this, key); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } return null; } public void print(Document doc) { try { lib.print(this, doc); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } } void interruption() { termthread.interrupt(); } void run() { termthread = Thread.currentThread(); while (true) { } } } Printer public class Printer { Thread pthread; boolean print(Document doc) { pthread = Thread.currentThread(); System.out.println("Printing " + doc.name); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("Print interrupted"); return false; }; return true; } public void interruption(Document doc) { pthread.interrupt(); } } but… • “tangled code” • code redundancy • difficult to reason about • difficult to change TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
clients call server client1 Server client2 worker 1 worker 2 worker 3 but… TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
a crosscutting concern holds * Document Library * search(key) print(doc) quota(user) ... holds * User uses user interruption cuts across the object structure accessed by * Printer * Terminal print(ps) getStatus() getQueue() ... gui() logon() search(key) print(doc) ... TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
aspect-oriented programming the AOP idea • crosscutting is inherent in complex systems • crosscutting concerns • have a clear purpose • have a natural structure • defined set of methods, module boundary crossings, points of resource utilization, lines of dataflow… • so, let’s capture the structure of crosscutting concerns explicitly... • in a modular way • with linguistic and tool support TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
language support for aspects Library Document public class Library { private Hashtable docs = new Hashtable(); private Hashtable users = new Hashtable(); private Printer printer; private class TerminalInfo { Terminal terminal; Thread thread; }; TerminalInfo term; Library(Printer p) { printer = p; for (int i = 0; i < 100 ; i++) { Document doc = new Document("book" + String.valueOf(i)); docs.put(doc, "book" + String.valueOf(i)); } for (int i = 0; i < 100 ; i++) { User user = new User("user" + String.valueOf(i)); users.put(user, "user" + String.valueOf(i)); } } public Document search(Terminal t, String key) { term.terminal = t; term.thread = Thread.currentThread(); try { return (Document)docs.get(key); } catch (Exception e) { System.out.println("Search interrupted at user's request"); } return null; } public boolean print(Terminal t, Document doc) { term.terminal = t; term.thread = Thread.currentThread(); try { return printer.print(doc); } catch (Exception e) { System.out.println("Print interrupted at user's request"); printer.interruption(doc); } return false; } public String quota(Terminal t, String username) { term.terminal = t; term.thread = Thread.currentThread(); try { User user = (User)users.get(username); if (user != null) return String.valueOf(user.quota); } catch (Exception e) { System.out.println("Quota query interrupted at user's request"); } return null; } public void interruption(Terminal t) { if (t == term.terminal) { term.thread.interrupt(); } } public static void main(String[] args) { Printer printer = new Printer(); Library lib = new Library(printer); Terminal term = new Terminal(lib); } } class Document { String name; Document(String n) { name = n; } } User class User { String name; int quota; User(String n) { name = n; } } Terminal public class Terminal { private Library lib; Thread termthread; Terminal (Library l) { lib = l; } public void logon() {} public void gui() {} public Document search(String key) { try { return lib.search(this, key); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } return null; } public void print(Document doc) { try { lib.print(this, doc); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } } void interruption() { termthread.interrupt(); } void run() { termthread = Thread.currentThread(); while (true) { } } } Printer public class Printer { Thread pthread; boolean print(Document doc) { pthread = Thread.currentThread(); System.out.println("Printing " + doc.name); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("Print interrupted"); return false; }; return true; } public void interruption(Document doc) { pthread.interrupt(); } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
OOP – the motivation void drawWindow(Window w) { drawBorders(w.borders); if ( w.isPopUp ) { … } got to get this code OO was about localizing this kind of concern TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
OOP – the language technology interface FigureElement { publicvoid draw(Graphics g); } class Point implements FigureElement { int _x = 0, _y = 0; : public void draw(Graphics g) { <do own thing> } } class Line implements FigureElement { : public void draw(Graphics g) { <do own thing> } } • explicit support for • message as goal • encapsulation • polymorphism • inheritance • some variation • class- vs. prototype-based • Java, C++, Smalltalk, CLOS vs. Self • single vs. multiple inheritance • Java, Smalltalk, Self vs. C++, CLOS analogy as follows? interface – crosscut class – aspect advice – method TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
OOP – the tool technology • tools preserve object abstraction • browse classes and methods • debug objects and methods TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
an example system a distributed digital library TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
the code Library Document public class Library { private Hashtable docs = new Hashtable(); private Hashtable users = new Hashtable(); private Printer printer; private class TerminalInfo { Terminal terminal; Thread thread; }; TerminalInfo term; Library(Printer p) { printer = p; for (int i = 0; i < 100 ; i++) { Document doc = new Document("book" + String.valueOf(i)); docs.put(doc, "book" + String.valueOf(i)); } for (int i = 0; i < 100 ; i++) { User user = new User("user" + String.valueOf(i)); users.put(user, "user" + String.valueOf(i)); } } public Document search(Terminal t, String key) { term.terminal = t; term.thread = Thread.currentThread(); try { return (Document)docs.get(key); } catch (Exception e) { System.out.println("Search interrupted at user's request"); } return null; } public boolean print(Terminal t, Document doc) { term.terminal = t; term.thread = Thread.currentThread(); try { return printer.print(doc); } catch (Exception e) { System.out.println("Print interrupted at user's request"); printer.interruption(doc); } return false; } public String quota(Terminal t, String username) { term.terminal = t; term.thread = Thread.currentThread(); try { User user = (User)users.get(username); if (user != null) return String.valueOf(user.quota); } catch (Exception e) { System.out.println("Quota query interrupted at user's request"); } return null; } public void interruption(Terminal t) { if (t == term.terminal) { term.thread.interrupt(); } } public static void main(String[] args) { Printer printer = new Printer(); Library lib = new Library(printer); Terminal term = new Terminal(lib); } } class Document { String name; Document(String n) { name = n; } } User class User { String name; int quota; User(String n) { name = n; } } Terminal public class Terminal { private Library lib; Thread termthread; Terminal (Library l) { lib = l; } public void logon() {} public void gui() {} public Document search(String key) { try { return lib.search(this, key); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } return null; } public void print(Document doc) { try { lib.print(this, doc); } catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(this); } } void interruption() { termthread.interrupt(); } void run() { termthread = Thread.currentThread(); while (true) { } } } Printer public class Printer { Thread pthread; boolean print(Document doc) { pthread = Thread.currentThread(); System.out.println("Printing " + doc.name); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("Print interrupted"); return false; }; return true; } public void interruption(Document doc) { pthread.interrupt(); } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
language support for aspects Library Document UserInterrupt public class Library { private Hashtable docs = new Hashtable(); private Hashtable users = new Hashtable(); private Printer printer; private class TerminalInfo { Terminal terminal; }; TerminalInfo term; Library(Printer p) { printer = p; for (int i = 0; i < 100 ; i++) { Document doc = new Document("book" + String.valueOf(i)); docs.put(doc, "book" + String.valueOf(i)); } for (int i = 0; i < 100 ; i++) { User user = new User("user" + String.valueOf(i)); users.put(user, "user" + String.valueOf(i)); } } public Document search(Terminal t, String key) { term.terminal = t; return (Document)docs.get(key); } public boolean print(Terminal t, Document doc) { term.terminal = t; return printer.print(doc); } public String quota(Terminal t, String username) { term.terminal = t; User user = (User)users.get(username); if (user != null) return String.valueOf(user.quota); } public static void main(String[] args) { Printer printer = new Printer(); Library lib = new Library(printer); Terminal term = new Terminal(lib); } } class UserRequestThreads { introduction (Terminal | Library | Printer) { Thread thread; void interruption() { thread.interrupt(); } } static advice (Document search(String key) | void print(Document doc)) & Terminal { catch (Exception e) { System.out.println("Operation interrupted at user's request"); lib.interruption(thisJoinPoint.object); } } static advice (Terminal & (Document search(String key) | void print(Document doc))) | (Library & (Document search(Terminal t, String key) | String quota(Terminal t, String username) | boolean print(Terminal t, Document doc))) | (Printer & boolean print(Document doc)) { before { thread = Thread.currentThread(); } } static advice Library & (Document search(Terminal t, String key) | String quota(Terminal t, String username)) { catch (Exception e) { System.out.println("Search interrupted at user's request"); return null; } } static advice Library & boolean print(Terminal t, Document doc) { catch (Exception e) { System.out.println("Search interrupted at user's request"); printer.interruption(doc); return false; } } static advice Printer & boolean print(Document doc) { catch (InterruptedException e) { System.out.println("Print interrupted"); return false; } } } class Document { String name; Document(String n) { name = n; } } User class User { String name; into quota; User(String n) { name = n; } } Terminal public class Terminal { private Library lib; Terminal (Library l) { lib = l; } public void logon() {} public void gui() {} public Document search(String key) { return lib.search(this, key); } } public void print(Document doc) { lib.print(this, doc); } void run() { termthread = Thread.currentThread(); while (true) { } } } Printer public class Printer { boolean print(Document doc) { System.out.println("Printing " + doc.name); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("Print interrupted"); return false; }; return true; } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
Document Library User Printer Terminal AspectJ • support for explicitly crosscutting concerns • smooth integration with Java • adds 3 new constructs make modules like this first class TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
return _x; return _y; _x = x; p1 semantic framework for Java class Point { privateint _x = 0, _y = 0; Point(int x, int y) { setXY(x,y); } int getX() { return _x; } int getY() { return _y; } void setX(int x) { _x = x; } void setY(int y) { _y = y; } void setXY(int x, int y) { _x = x; _y = y; } void draw(Graphics g) { … } } when a “void setX(int)”message* is received bya point, do this setX(3) TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
a return valueor exception is received by this object an value is returned or an exception is thrown by this object a method is called on an object the actual method starts executing the method callleaves this object a method call to another object the join points key points in runtime object interaction a Client dispatch a Server dispatch TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
a “void setX(int)” message name and parameters a “void setY(int)” message and or any point in aninstanceof Server setX(3) <a point> setY(11) denotes certain join points the pointcut construct pointcut requests(): Server & (int newJob(String) | StringjobStatus(int)); whenever a Server receives“int newJob(String)” or “String jobStatus(int)” calls TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
the crosscut construct can cut across multiple classes crosscut moves(): (Point & (void setX(int) | void setY(int))) | (Line & (void setP1(Point) | void setP2(Point))); TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
additional action to take at crosscut the advice construct crosscut moves(): (Point & (void setX(int) | void setY(int))) | (Line & (void setP1(Point) | void setP2(Point))); static after(): moves() { <runs after moves> } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
an aspect is a crosscutting concern a simple aspect class TrackMoves { static boolean _flag = false; static boolean testAndClear() {boolean result = _flag; _flag = false; return result; } crosscut moves(): (Point & (void setX(int) | void setY(int))) | (Line & (void setP1(Point) | void setP2(Point))); static after(): moves() { _flag = true; } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
crosscut signature typed variable in place of type name matches signature advice parameters using context in advice • crosscut can explicitly expose certain values • advice can use value crosscut moves(Object o): o & ((Point & (void setX(int) | void setY(int))) | (Line & (void setP1(Point) | void setP2(Point)))); static after(Object o): moves(o) {<o is bound to object> } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
using context in advice class TrackMoves { static Set _movers = new HashSet(); static Set getMovers() { Set result = _movers; _movers = new HashSet(); return result; } crosscut moves(Object o): o & ((Point & (void setX(int) | void setY(int))) | (Line & (void setP1(Point) | void setP2(Point)))); static advice(Object o): moves(o) { after { _movers.add(o); } } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
advice is additional action to take at a join points • before before proceeding at join point • after returning a value to join point • after throwing a throwable to join point • after return to join point either way • around before, with explicit control over when&if program proceeds at join point TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
after advice class BoundsChecker { crosscut sets(Point p): p & (void setX(int) | void setY(int)); staticadvice (Point p): sets(p) { after { assert(p.getX() >= MIN_X); assert(p.getX() <= MAX_X); assert(p.getY() >= MIN_Y); assert(p.getY() <= MAX_Y); } } staticvoid assert(boolean v) { if ( !v ) thrownew RuntimeException(…); } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
before advice class BoundsChecker { static advice(Point p, int newX): p & void setX(newX) { before { assert(newX >= MIN_X); assert(newX <= MAX_X); } } static advice(Point p, int newY): p & void setY(newY) { before { assert(newY >= MIN_Y); assert(newY <= MAX_Y); } }static void assert(boolean v) {if ( !v ) thrownew RuntimeException(…); }} TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
around advice class BoundsEnforcer { static advice(Point p, int newX) returns void: p & void setX(newX) { around { thisJoinPoint.runNext(p, clip(newX, MIN_X, MAX_X)); } } staticadvice(Point p, int newY) returns void: p & void setY(newY) { around { thisJoinPoint.runNext(p, clip(newY, MIN_X, MAX_X)); } }staticint clip(int val, int min, int max) {return Math.max(min, Math.min(max, val)); } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
add time: when connection is dropped 0..N total time connected Call Customer 1 1 1 0..N start timing: when there’s a new connection stop timing: when connection is dropped caller time each connection Connection receiver an asymmetric multi-object protocol • trivial telecom system • crosscutting concerns are: • timing • consistency checks • ... TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
a variable in Connection that only Timing can see a variable in Customer that only Timing can see proper accessor for the total connect time timing aspect implementation class Timing { private Timer Connection.timer = new Timer(); privatelong Customer.totalConnectTime = 0; publicstaticlong getCustomerTotalConnectTime(Customer c) {return c.totalConnectTime; } : : the aspect state crosscuts the objects proper access is through the aspect TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
timing aspect implementation crosscut startTiming(Connection c): c & void complete(); crosscut endTiming(Connection c): c & void drop(); staticadvice(Connection c): startTiming(c) { after { c.timer.start(); } } staticadvice(Connection c): endTiming(c) { after { c.timer.stop(); c.getCaller().totalConnectTime += c.timer.getTime(); c.getReceiver().totalConnectTime += c.timer.getTime(); } } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
wildcarding in crosscuts shapes.util.Point shapes..* types Point & public * *(..) shapes..* & !privateint *(..) messages (Point | Line) & new(..) shapes..* & new(..) instantiations handling exceptions * *(..) & handle(RMIException) “..” is a multiple-part wild card “*” is a single-part wild card TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
property-based crosscuts class LogPublicErrors { static Log log = new Log(); crosscut publicInterface (): mypackage..* & ( public * *(..) | publicnew(..) ); static advice(): publicInterface() { after throwing (Error e) { log.write(e); } } } • consider another programmer adding public method • i.e. extending the public interface • this code will automatically capture that TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
clients call server client1 Server client2 server ends up calling workers, through many levels worker 1 worker 2 worker 3 context-dependent functionality • workers need to know client: • capabilities • charge backs • to customize result TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
context passing crosscuts crosscut entryPoints(): Server & (void doService1(Object) | void doService2()); client1 Server client2 worker 1 worker 2 worker 3 TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
client1 Server client2 worker 1 worker 2 worker 3 context passing crosscuts crosscut entryPoints(): Server & (void doService1(Object) | void doService2()); crosscut invocations(Client c): c & calls(entryPoints()); TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
client1 Server client2 worker 1 worker 2 worker 3 context passing crosscuts crosscut entryPoints(): Server & (void doService1(Object) | void doService2()); crosscut invocations(Client c): c & calls(entryPoints()); crosscut clientScope(Client c): cflow(invocations(c)); TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
client1 Server client2 worker 1 worker 2 worker 3 context passing crosscuts crosscut entryPoints(): Server & (void doService1(Object) | void doService2()); crosscut invocations(Client c): c & calls(entryPoints()); crosscut clientScope (Client c): cflow(invocations(c)) & workPoints(); crosscut workPoints(): (ServiceHelper1 & void doWorkItemA()) | (ServiceHelper2 & void doWorkItemB()) | (ServiceHelper3 & void doWorkItemC()); TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology
context passing crosscuts class HandleChargebacks { crosscut entryPoints(): Server & (void doService1(Object) | void doService2());crosscut invocations(Client c): c & calls(entryPoints()); crosscut clientWork(Client c): cflow(invocations(c)) & workPoints(); crosscut workPoints(): (ServiceHelper1 & void doWorkItemA()) | (ServiceHelper2 & void doWorkItemB()) | (ServiceHelper3 & void doWorkItemC()); static advice (Client c): clientWork(c) { before { c.chargeback(); } } } TS-1505, AspectJ: Aspect-Oriented Programming Using JavaTM Technology