Aspect-Oriented Programming and Aspectj
Total Page:16
File Type:pdf, Size:1020Kb
What is Aspect-Oriented Programming? Many possible answers: • a fad • a way-too-general collection of cross-cutting Aspect-Oriented programming techniques Programming and AspectJ • a new name for old ideas (generators, domain- specific languages, MOPs) • Aspect-oriented programming is a common buzzword lately • the solution to all our problems • Papers from ECOOP 1997 (early overview— My opinion: AOP is just a new name for old the manifesto), ECOOP 2001 (overview of ideas, but these ideas are good AspectJ) - dominant AOP implementations (e.g., AspectJ) are MOP-like, but they don’t • Kiczales (the team leader) was behind the need to be CLOS MOP An aspect is a piece of functionality that cross- cuts functional units of a system 1 of 18 2 of 18 Yannis Smaragdakis Yannis Smaragdakis Simple Working Example (bad, IMO) Aspect-Oriented Principles • Image processing application with filters • A component is a part of the implementation - filters need to be kept separate that is localized in traditional languages (Java/ - filters need to be fused together for C/C++, etc.) optimization (e.g., loop fusion) • An aspect is a part of the implementation that (defun or! (a b) is not well-localized with traditional languages (let ((result (new-image))) (code ends up being scattered everywhere) (loop for i from 1 to width do (loop for j from 1 to height do • AOP tries to offer language support for (set-pixel result i j expressing aspects concisely and separately (or (get-pixel a i j) (get-pixel b i j))))) from components result)) • Join points: the points where components • If another filter has the same looping structure, interact and aspects can influence them the two should be fused together (for locality, max memory consumption, etc.) • Elements of an AOP-based implementation: - a component language part • Better example: in distributed apps, - an aspect language part synchronization/serialization of data/failure - an aspect weaver applying the aspects to handling are orthogonal to other functionality components (really, a generator) 3 of 18 4 of 18 Yannis Smaragdakis Yannis Smaragdakis Image Processing Example Revisited Other Example Essentially, a domain-specific language is • How data is serialized (and, in particular, how designed for image processing much data is copied) in a distributed system is an issue independent of the system’s main • Component language: implicit loop structure functionality (define-filter or! (a b) • A communication aspect language can allow (pixelwise (a b) (aa bb) (or aa bb))) the programmer to describe how much of an (aa, bb are iterators—standard Lisp/Scheme object will be copied iterator binding semantics) - again, just a domain-specific language/ generator. You can call it AOP, but the • Aspect language: operations on nodes in the value is in the domain dataflow graph. E.g., if two loops have the - there is a general system called Doorastha same structure and inputs, fuse them together that does similar things in Java • Weaver: represent the component program as a • E.g., a digital library may have Book and flow graph, run aspect code on it, generate Repository classes. We can tell the system code from higher-level abstractions to only copy parts of a Book object when registering and unregistering it in a remote repository 5 of 18 6 of 18 Yannis Smaragdakis Yannis Smaragdakis Example aspect program: AspectJ remote Repository { void register (Book); • A very nice MOP/general compositional void unregister (Book: copy isbn); semantic extensibility facility for Java // Book class has “isbn” field Book: copy isbn lookup(String); - used entirely for interposing code, not // method: “lookup”, return type: Book changing how the object system works } - AspectJ is a transparent extension of Java, comes with IDE support (for easier editing, inspection of aspect code) • To demonstrate, consider an example application: a figure editor FigureEle incrXY Point Line getX getX setX setX incrXY incrXY move aspect 7 of 18 8 of 18 Yannis Smaragdakis Yannis Smaragdakis Join points Kinds of Pointcuts • Many possible join points in AspectJ. At: • Pointcuts can be thought of as runtime - method call (inside calling object) predicates: when they are true, we are at a join - method call reception by an object (any point described by the pointcut. method) - method execution (specific method) • Several kinds of pointcuts. E.g.: - field access (get/set) - call(signature) - constructor call (inside object doing new) - execution( signature) - constructor call reception (any constructor) - get/set(signature) - value can be matched with args - exception handler execution - args(Type) - class initialization (static initializers run) - handler(ThrowableClass) - this/target( Type) Pointcuts - within(Type) - withincode(signature) • Pointcut = set of join points + values from the - cflow(pointcut) context (e.g., the object, method this - initialization( ConstrSig) parameters, etc.) - staticinitialization( Type) call(void Point.setX(int)) • Also: boolean pointcut operators ( , , etc.) - all join points where the method called is && || and pointcut constants (user-defined pointcuts) void Point.setX(int) 9 of 18 10 of 18 Yannis Smaragdakis Yannis Smaragdakis Pointcut Example Aspects pointcut moves(): • Aspects have class-like syntax (and, to some call(void FigureElement.incrXY(int,int)) ||call(void Line.setP1(Point)) extent, semantics—e.g., for scoping). They can || call(void Line.setP2(Point)) contain pointcuts, advice, and regular class || call(void Point.setX(int)) || call(void Point.setY(int)); declarations (member vars/methods) aspect MoveTracking { • describes the join points where methods that static boolean flag = false; cause “movement” of a figure are called static boolean testAndClear() { - Note that a “user-defined” pointcut boolean result = flag; flag = false; (operator pointcut ) is used to give a return result; name (moves) to the pointcut } pointcut moves(): Advice call(void FigureElement.incrXY(int,int)) ||call(void Line.setP1(Point)) • Advice: specification of aspect code to be || call(void Line.setP2(Point)) || call(void Point.setX(int)) interposed at pointcuts || call(void Point.setY(int)); - before, after, or instead of (around) the code at a join point after(): moves() {// advice flag = true; - two special cases of “after”: after returning/after } throwing (for normal/exception exits) } 11 of 18 12 of 18 Yannis Smaragdakis Yannis Smaragdakis Aspects Pointcut Parameters • Aspects can have multiple instances • Advice and pointcut definitions can have parameters (see empty parentheses in previous • There are complex rules about how aspect examples) execution (advice application) is ordered - the rules take into account Aspect • The parameters can be used in pointcut relationships (e.g., if aspect A extends B, predicates instead of type variables and take then it’s considered more specific) the value of the instance matching the - there is a dominates keyword for aspects predicate that know about each other - this is overloading the existing syntax for an entirely different purpose Example (uses MoveTracking from last slide) before(Point p, int nval): call(void p.setX(nval)) { aspect Mobility dominates MoveTracking { System.out.println(“x value of” + p + static boolean enableMoves = true; “ will be set to ” + nval + “.”); } around() returns void: MoveTracking.moves() { if (enableMoves) proceed(); } To print a message every time the value of x for } a point changes defines an “around” (instead-of) method Example: Getting the current object preventing moves if the flag is not set 13 of 18 14 of 18 Yannis Smaragdakis Yannis Smaragdakis • regular pointcut definition: Abstract and Generic Aspects pointcutfoo(): instanceof(Point); A “virtual type”-like mechanism allows aspect genericity • pointcut with parameter: abstract aspect SimpleTracing { pointcut foo(Pointp): abstract pointcut tracePoints(); instanceof(p); //yet undefined before(): tracePoints() { • p is the object of class Point with which the printMessage(“Entering”,thisJoinPoint); join point is associated! } after(): tracePoints() { printMessage(“Exiting”,thisJointPoint); Example: Around Advice and Proceed } • We saw proceed earlier, but it can also be void printMessage(String s, JoinPoint tjp) called with parameters { ... } } • To ensure that a method is only called with aspect XYTracing extends SimpleTracing { non-negative int arguments: pointcut tracePoints(): call( around(int nv) returns void: void FigureElement.incrXY(int,int)); call(void Point.setX(nv)) } {proceed(Math.max(0, nv)); } - (note the thisJointPoint variable and the JoinPoint type: they reflectively export details of the AspectJ implementation) 15 of 18 16 of 18 Yannis Smaragdakis Yannis Smaragdakis Wildcards Introductions / Inter-type Declarations E.g., Can declare members and supertypes for existing classes! call(* Point.*(..)) call(Point.new(..)) A static transformation language. These “introductions” are not advice and are not Control-Flow Based Pointcuts associated with pointcuts The cflow operator is true on points under the dynamic extent of other join points (e.g., while Add an “enabled” field to all the methods corresponding to these join points FigureElement s: are still active on the execution stack) - boolean FigureElement.enabled=false; pointcut moves(FigureElement fe): Add a setter method: <see before>; - public FigureElement.setEnabled(boolean b) { pointcut topLevelMoves(FigureElement fe): this.enabled = b; moves(fe) &&!cflow(moves(FigureElement)); } Implementation Add superclasses to FigureElement: - declare parents: The AspectJ compiler inserts code to check and FigureElement extends Drawable call the right aspects at join points: efficient 17 of 18 18 of 18 Yannis Smaragdakis Yannis Smaragdakis.