AspectOriented Programming OOD Course Solange Karsenty What is

  • Slides: 54
Download presentation
Aspect-Oriented Programming OOD Course Solange Karsenty

Aspect-Oriented Programming OOD Course Solange Karsenty

What is it? l A new addition to the world of programming l Key

What is it? l A new addition to the world of programming l Key advantage: separation of concerns • New concepts & language constructs • New tools (aspect compiler, browser, debugger) • Many examples & patterns of practical use • A lot of hype • Cross-cutting concerns: those that are not well • encapsulated in the usual OOD way – classes Often appear in the form of ‘code guidelines’ 07 December 2020 Object Oriented Design Course 2

For Example public class Some. Class extends Other. Class { // Core data members

For Example public class Some. Class extends Other. Class { // Core data members // Other data members: Log stream, consistency flag public void Do. Something(Operation. Information info) { // Ensure authentication // Ensure info satisfies contracts // Lock the object in case other threads access it // Ensure the cache is up to date // Log the start of operation // ==== Perform the core operation ==== // Log the completion of operation // Unlock the object // Do Standard Exception Handling } // More operations similar to above } 07 December 2020 Object Oriented Design Course 3

Crosscutting Concerns What is a crosscutting concern? l Behavior that cuts across the typical

Crosscutting Concerns What is a crosscutting concern? l Behavior that cuts across the typical divisions of • responsibility, such as logging or debugging A problem which a program tries to solve. • Aspects of a program that do not relate to the • core concerns directly, but which proper program execution nevertheless requires. 12/7/2020 Object Oriented Design Course 4

History Developed at Xerox PARC (Palo Alto RC) l Launched in 1998 l PARC

History Developed at Xerox PARC (Palo Alto RC) l Launched in 1998 l PARC transferred Aspect. J to an openly- l developed eclipse. org project in December of 2002. For more info: www. eclipse. org/aspectj 12/7/2020 Object Oriented Design Course 5

Cross-Cutting Concerns l l l l l Logging Debugging Profiling (Performance) Security & Authentication

Cross-Cutting Concerns l l l l l Logging Debugging Profiling (Performance) Security & Authentication Exception Handling Design by Contract Event Handling Synchronization Resource Pooling Others… 07 December 2020 Object Oriented Design Course 6

Problems l Code Tangling : • when two or more concerns are implemented in

Problems l Code Tangling : • when two or more concerns are implemented in the same body of code or component, making it more difficult to understand. Changes to one implementation may cause unintended changes to other tangled concerns. • lines of relatively high-level code distract the main flow of control in a component’s implementation The problem of tangled code means that within software systems code exists, which is on one • hand redundant but on the other hand cannot be encapsulated by separate modules using regular techniques • tangled code is extremely difficult to maintain, since small changes to the functionality require mentally untangling and then re-tangling l Code Scattering: • when similar code is distributed throughout many program modules • l occurs when a concern or feature of a software system mismatches with • • existing modularity of the system the programming language's modularity mechanisms Reduced reuse, speed, quality, ability to change 07 December 2020 Object Oriented Design Course 7

Current Solutions l l l Design patterns can solve some problems • • Proxy,

Current Solutions l l l Design patterns can solve some problems • • Proxy, Template Method solve some cases Visitor, Strategy solve other cases Frameworks provide domain-specific solutions But it’s not a solution for cases in which: • • Polymorphism can’t be used (exceptions, Db. C) Concerns are only used during debug, and change a lot The designer didn’t plan for a given concern The framework wasn’t designed to consider a concern 07 December 2020 Object Oriented Design Course 8

Separation of Concerns l Separate logical concerns should be in separate modules of code

Separation of Concerns l Separate logical concerns should be in separate modules of code – called aspects

OOD & AOP l Object-Oriented Programming l Aspect-Oriented Programming l AOP complements OOD •

OOD & AOP l Object-Oriented Programming l Aspect-Oriented Programming l AOP complements OOD • Basic concept of modularity : the class • Good for common concerns (inheritance) • A program is a set of classes • Basic concept of modularity: the aspect • Good for unrelated concerns (pointcuts) • A program is a set of aspects 07 December 2020 Object Oriented Design Course 10

Aspect. J l Aspect. J is the leading AOP implementation, and the only full,

Aspect. J l Aspect. J is the leading AOP implementation, and the only full, stable and widely used one It includes a language specification l It includes a set of tools l • A set of additions to the Java language • A compiler that creates standard Java bytecode • Aspect-aware debugger and documentation tool • Visual aspect browser • Integration with popular IDEs 07 December 2020 Object Oriented Design Course 11

Hello, World Let’s start with a simple example // Hello. World. java l public

Hello, World Let’s start with a simple example // Hello. World. java l public class Hello. World { public static void say(String message) { System. out. println(message); } public static void say. To. Person( String message, String name) { System. out. println(name + ", " + message); } } 07 December 2020 Object Oriented Design Course 12

Polite Hello, World l Guess what the following aspect does // Manners. Aspect. java

Polite Hello, World l Guess what the following aspect does // Manners. Aspect. java public aspect Manners. Aspect { pointcut call. Say. Message() : call(public static void Hello. World. say*(. . )); before() : call. Say. Message() { System. out. println("Good day!"); } after() : call. Say. Message() { System. out. println("Thank you!"); } } 07 December 2020 Object Oriented Design Course 13

Running the Example l Just Compile and Run l What’s in the example •

Running the Example l Just Compile and Run l What’s in the example • ajc Hello. World. java Manners. Aspect. java (or *. aj) • ajc –argfile Polite. Hello. World. lst • A Pointcut defines at which points in the dynamic • • execution of the program – at what Join Points – extra code should be inserted An Advice defines when, relative to the join point, the new code runs, and that actual code An Aspect encapsulates pointcuts and advices 07 December 2020 Object Oriented Design Course 14

Join Points l l Well-defined points in a program’s execution Aspect. J makes these

Join Points l l Well-defined points in a program’s execution Aspect. J makes these join points available: • Method call and execution • Constructor call and execution • Read/write access to a field • Exception throwing or handler execution • Object and class initialization execution A join point may include other join points A join point may have a context 07 December 2020 Object Oriented Design Course 15

Join Points Method-execution Constructor-call Method-call “Test. main(. . )” “Point(. . ) ” “Point.

Join Points Method-execution Constructor-call Method-call “Test. main(. . )” “Point(. . ) ” “Point. incr. XY (. . )” Staticinitialization “Point. _clinit_” public class Test{ public static void main(String[] args) { Point pt 1 = new Point(0, 0); pt 1. incr. XY(3, 6); } } Preinitialization Initialization Constructor-execution Field-set “Point(. . )” Field-set “Point(. . ) Point. x ” ”” “Point. y” Method-execution Field-set Point. incr. XY (. . )” “Point. x ” “Point. y” public class Point { private int x; private int y; public Point(int x, int y) { this. x = x; this. y = y; } public void incr. XY(int dx, int dy){ x=+dx; y=+dy; }

Pointcuts Definition of a collection of join points l plus, optionally, some of the

Pointcuts Definition of a collection of join points l plus, optionally, some of the values in the execution context of those join points. Can be composed using boolean operators || , && Matched at runtime l 12/7/2020 Object Oriented Design Course 17 l

Pointcuts l Most common kind – the call pointcut: • call(public void My. Class.

Pointcuts l Most common kind – the call pointcut: • call(public void My. Class. my. Method(String)) • call(void My. Class. my. Method(. . )) • call(* My. Class. my. Method*(. . )) // * means wildcard • call(* My. Class. my. Method*(String, . . )) • call(* *. my. Method(. . )) • call(My. Class. new(. . )) • call(My. Class+. new(. . )) // + is subclass wildcard • call(public * com. mycompany. *. *(. . )) 07 December 2020 Object Oriented Design Course 18

Example 12/7/2020 Object Oriented Design Course 19

Example 12/7/2020 Object Oriented Design Course 19

Pointcuts Example call(public void Point. set. X(int)) Matches if the join point is a

Pointcuts Example call(public void Point. set. X(int)) Matches if the join point is a method call with this signature. call(public void Figure. Element. incr. XY(int, int)) Matches if the join point is a method call to any kind of figure element. call(public void Point. set. X(int))|| call(public void Point. set. Y(int)) Matches any call to set. X OR set. Y !this(Figure. Element)&& call(public void Figure. Element. incr. XY(int, int)) Matches all method calls to incr. XY that come from an object of another type, as well as calls from static methods 12/7/2020 Object Oriented Design Course 20

Example User-defined pointcut designators moves() Pointcut moves(): call(void Figure. Element. incr. XY(int, int))|| call(void

Example User-defined pointcut designators moves() Pointcut moves(): call(void Figure. Element. incr. XY(int, int))|| call(void Line. set. P 1(Point)) || call(void Line. set. P 2(Point)) || call(void Point. set. X(int)) || call(void Point. set. Y(int))

Advice Method-like mechanism used to declare l that certain code should execute at each

Advice Method-like mechanism used to declare l that certain code should execute at each of the join points in the pointcut. Advice: l before • around • after returning • after throwing • 12/7/2020 Object Oriented Design Course 22

Pointcut parameters and this. Join. Point Parameters Exposes certain values that are in the

Pointcut parameters and this. Join. Point Parameters Exposes certain values that are in the execution context of the join points. The advice’s pointcut publishes the values for the advice args. Primitives: this, target and args before(Point p, int nval): call(void Point. set. X(int) ) && target(p) && args(nval){ if(nval>MAXBOUND) System. out. println(“The value is too big !”); else System. out. println(“x value of “+p+” will be set to : “+nval); } 12/7/2020 Object Oriented Design Course 23

Pointcut parameters and this. Join. Point Simple reflective access to information about the •

Pointcut parameters and this. Join. Point Simple reflective access to information about the • current join point. Notice that this is very useful for debugging and tracing purposes. before(): call(void Point. set. X(int)){ if ( ( (Integer)this. Join. Point. get. Args()[0]). int. Value() > 10) System. out. println("The value is too big !"); else System. out. println("x value of ” +this. Join. Point. get. Target() +" will be set to” +this. Join. Point. get. Args()[0]); } 12/7/2020 Object Oriented Design Course 24

Example 1: Tracing l l l Print debug traces of method calls and their

Example 1: Tracing l l l Print debug traces of method calls and their timing for all methods of class My. Class Note the use of anonymous pointcuts methods that are traced do not need to be edited public aspect My. Class. Trace { before() : call(public * My. Class. *(. . )) { System. out. println("Before: " + this. Join. Point + " " + System. current. Time. Millis()); } after() : call(public * My. Class. *(. . )) { System. out. println("After: " + this. Join. Point + " " + System. current. Time. Millis()); } } 07 December 2020 25 Object Oriented Design Course

this. Join. Point A useful reflection-like feature, can provide: l l l l the

this. Join. Point A useful reflection-like feature, can provide: l l l l the kind of join point that was matched the source location of the current join point normal, short and long string representations of the current join point actual argument(s) to the method / field of the join point signature of the method or field of the current join point the target object the currently executing object a reference to the static portion of the object holding the join point; also available in this. Join. Point. Static. Part 07 December 2020 Object Oriented Design Course 26

Example 2: Tracing Revisited l First solution using an aspect: aspect Trace. Entities {

Example 2: Tracing Revisited l First solution using an aspect: aspect Trace. Entities { pointcut my. Classes(): within(My. Class+); pointcut my. Constructors(): my. Classes() && call(new(. . )); pointcut my. Methods(): my. Classes() && call(* *(. . )); before (): my. Constructors() { Trace. trace. Entry(“Before Constructor: "+ this. Join. Point. Static. Part. get. Signature()); } before (): my. Methods() { Trace. trace. Entry(“Before Method: " + this. Join. Point. Static. Part. get. Signature()); } 07 December 2020 Object Oriented Design Course 27

Within and CFlow Pointcuts l Be inside lexical scope of class or method l

Within and CFlow Pointcuts l Be inside lexical scope of class or method l Be inside the control flow of another pointcut • within(My. Class) // of class • withincode(* My. Class. my. Method(. . )) // of method • If a() calls b(), then b() is inside a()’s control flow • cflow ( call(* My. Class. my. Method(. . ) ) • Any pointcut can be used as the base of cflow • Control flow is decided in runtime, unlike within • cflowbelow(Pcut) is similar, but ignores join points that are already in PCut 07 December 2020 Object Oriented Design Course 28

Example 3: Contract Enforcement l l Useful to check assertions, use Design by Contract,

Example 3: Contract Enforcement l l Useful to check assertions, use Design by Contract, or validate framework assumptions The following checks that only certain factory methods can put objects in a central Registry aspect Registration. Protection { pointcut register(): call(void Registry. register(Element)); pointcut can. Register(): withincode(static * Element. make*(. . )); before(): register() && !can. Register() { throw new Illegal. Access. Exception("Illegal call " + this. Join. Point); } } 07 December 2020 Object Oriented Design Course 29

Example 4: Profiling l l It’s easy to ask very specific questions, and quickly

Example 4: Profiling l l It’s easy to ask very specific questions, and quickly modify them, all outside the real code Note that withincode wouldn’t work here aspect Sets. In. Rotate. Counting { int rotate. Count = 0; int set. Count = 0; before(): call(void Line. rotate(double)) { rotate. Count++; } before(): call(void Point. set*(int)) && cflow(call(void Line. rotate(double))) { set. Count++; } } 07 December 2020 Object Oriented Design Course 30

Context-Based Pointcuts l Pointcuts based on dynamic, runtime context • • this(JComponent+) // ‘this’

Context-Based Pointcuts l Pointcuts based on dynamic, runtime context • • this(JComponent+) // ‘this’ object inherits from JComponent target(My. Class) // match target object of current method call args(String, . . , int) // match order & type of arguments args(IOException) // type of argument or exception handler l Dynamic – so these are not equal: l Always used in conjunction with other pointcuts • call(* Object. equals(String)) • call(* Object. equals(Object)) && args(String)) 07 December 2020 Object Oriented Design Course 31

Exposing Context in Pointcuts l Recall: a pointcut can define arguments • Each argument

Exposing Context in Pointcuts l Recall: a pointcut can define arguments • Each argument must have a type • Each must be bound by a context-based pointcut • The arguments can be passed to the advice l Here’s another custom tracing example: aspect Trace. Point { pointcut set. XY(Figure. Element fe, int x, int y): call(void Point. set. XY(int, int)) && target(fe) && args(x, y); after(Figure. Element fe, int x, int y): set. XY(fe, x, y) { System. out. println(fe + " moved to (" + x + ", " + y + "). "); } } 07 December 2020 Object Oriented Design Course 32

Example 5: Pre- and Post-Conditions l Verify that set. X() and set. Y() in

Example 5: Pre- and Post-Conditions l Verify that set. X() and set. Y() in class Point do not receive out-of-bound arguments aspect Point. Bounds. Checking { pointcut set. X(int x): call(void Point. set. X(int)) && args(x)); pointcut set. Y(int y): call(void Point. set. Y(int)) && args(y)); before(int x): set. X(x) { if ( x < MIN_X || x > MAX_X ) throw new Illegal. Argument. Exception("x out of bounds"); } before(int y): set. Y(y) { if ( y < MIN_Y || y > MAX_Y ) throw new Illegal. Argument. Exception("y out of bounds"); } } 07 December 2020 Object Oriented Design Course 33

Execution Pointcuts l l Join point in which a method starts executing • •

Execution Pointcuts l l Join point in which a method starts executing • • Behaviors different form call pointcuts • • • l execution(* My. Class. my. Method*(. . )); execution(My. Class+. new(. . )) In execution, the within and withincode pointcuts will refer to the text of the called method In execution, The dynamic context pointcuts will refer to the context of the called method call does not catch calls to (non-static) super methods Use call to match calling a signature, use execution for actually running a piece of code 07 December 2020 Object Oriented Design Course 34

Advice l l l Defines the code to run, and when to run it

Advice l l l Defines the code to run, and when to run it Advice kinds: before(), after() and around() Before advice runs before the join point After advice has three variants • • • after(): register() { registry. update(); } after() returning move() { screen. update(); } after() throwing (Error e): { log. write(e); } around advice surrounds original join point • • • Can replace it completely, and return a different value Can run it one or more times with proceed() Can run it using different arguments 07 December 2020 Object Oriented Design Course 35

Example 6: Resource Pooling l A global connection pool should be used • •

Example 6: Resource Pooling l A global connection pool should be used • • Original code is not aware of the pool, so the following code surrounds Connection. close() To complete the implementation, the constructor of class Connection must be surrounded as well void around(Connection conn) : call(Connection. close()) && target(conn) { if (enable. Pooling) { connection. Pool. put(conn); } else { proceed(); } } 07 December 2020 Object Oriented Design Course 36

More Pointcut Kinds l Field access l Exception handling (entering catch execution) l Conditional

More Pointcut Kinds l Field access l Exception handling (entering catch execution) l Conditional tests • get(Print. Stream System. out) • set(int My. Class. x) • handler(Remote. Exception) • handler(IOException+) • handler(Credit. Card*) • if(Event. Queue. is. Dispatch. Thread()) • The Boolean expression can use static methods and fields, fields of the enclosing aspect, and this. Join. Point 07 December 2020 Object Oriented Design Course 37

Example 7: Error Logging l l Log all errors (not exceptions) thrown out of

Example 7: Error Logging l l Log all errors (not exceptions) thrown out of package com. acme. * to a log Use cflow() to prevent logging an error twice, in case it was raised internally in com. acme. * aspect Public. Error. Logging { pointcut public. Method. Call(): call(public * com. acme. *. *(. . )); after() throwing (Error e): public. Method. Call() && !cflow(public. Method. Call()) if (Logger. trace. Level() > 0) { Logger. write(e); } } 07 December 2020 Object Oriented Design Course 38

Aspects l l l Unit that combines pointcuts and advices Can contain methods and

Aspects l l l Unit that combines pointcuts and advices Can contain methods and fields Can extend classes or implement interfaces Cannot create an ‘aspect object’ using new Aspects and pointcuts can be abstract Classes can define pointcuts too • These must be declared static • This is not recommended practice • Advices can’t be declared inside classes 07 December 2020 Object Oriented Design Course 39

Fields in Methods in Aspects l Fields can be used to collect data •

Fields in Methods in Aspects l Fields can be used to collect data • See example 4 – profiling l Methods can be used as in any regular class aspect Yet. Another. Logging. Aspect { private static Log log = new Log(); public static void clear. Log() { log. clear(); } pointcut public. Method. Call(): call(public * com. acme. *. *(. . )); after() throwing (Error e): public. Method. Call() { log. write(e); } } l Aspects are by default singletons • But there are other supported association types: perthis, pertarget, percflowbelow 07 December 2020 Object Oriented Design Course 40

Example 7: Authentication l l Abstract aspects allow even more reuse Here’s a generic

Example 7: Authentication l l Abstract aspects allow even more reuse Here’s a generic aspect for authentication through a singleton Authenticator: // Abstratc. Authentication. Aspect. java public abstract aspect Abstract. Authentication. Aspect { public abstract pointcut ops. Needding. Authentication(); before() : ops. Needding. Authentication() { // Perform authentication. If not authenticated, // let the thrown exception propagate. Authenticator. authenticate(); } } 07 December 2020 Object Oriented Design Course 41

Example 7: Authentication II l A concrete aspect for a database app: // Database.

Example 7: Authentication II l A concrete aspect for a database app: // Database. Authentication. Aspect. java public aspect Database. Authentication. Aspect extends Abstract. Authentication. Aspect { public pointcut ops. Needding. Authentication(): call(* Database. Server. connect()); } 07 December 2020 Object Oriented Design Course 42

Example 8: Functional Guidelines l “Every time a slow operation is used, the cursor

Example 8: Functional Guidelines l “Every time a slow operation is used, the cursor should turn into a wait cursor” public abstract aspect Slow. Method. Aspect { abstract pointcut slow. Methods(UIManager ui); void around(UIManager ui) : slow. Methods(ui) { Cursor original. Cursor = ui. get. Cursor(); Cursor wait. Cursor = Cursor. WAIT_CURSOR; ui. set. Cursor(wait. Cursor); try { proceed(ui); } finally { ui. set. Cursor(original. Cursor); } } } 07 December 2020 Object Oriented Design Course 43

Functional Guidelines l l l Code of aspected classes doesn’t change Multiple aspects can

Functional Guidelines l l l Code of aspected classes doesn’t change Multiple aspects can co-exist Same pattern is useful for many other cases • Security • Resource Pooling, Caching, Copy on write, … • Creation by Factory, Lazy Creation, … • Multi-Thread Synchronization • Transaction Definition • Monitoring System Notification • Standard Exception Handling 07 December 2020 Object Oriented Design Course 44

Introductions l Modify the static form of a class Add fields to an existing

Introductions l Modify the static form of a class Add fields to an existing class l Add methods to an existing class l Add Constructors l • private boolean Server. disabled = false; • public String Foo. name; • public int Point. get. X() { return x; } • public String (Point || Line). get. Name() { return name; } • public Point. new(int x, int y) { this. x = x; this. y = y; } 07 December 2020 Object Oriented Design Course 45

Introductions II l Extend an existing class with another l Implement an interface with

Introductions II l Extend an existing class with another l Implement an interface with an existing class l “Soften” Exception • declare parents: Point extends Geometric. Object; • declare parents: Point implements Comparable; • Convert checked exceptions to unchecked ones • Wraps exceptions in org. aspectj. lang. Soft. Exception • declare soft: Clone. Not. Supported. Exception: execution(Object clone()); 07 December 2020 Object Oriented Design Course 46

Example 9: Adding Mixins l Given a standard Point class, with private fields x,

Example 9: Adding Mixins l Given a standard Point class, with private fields x, y we can make it cloneable: aspect Cloneable. Point { declare parents: Point implements Cloneable; declare soft: Clone. Not. Supported. Exception: execution(Object clone()); Object Point. clone() { return super. clone(); } } l Being Cloneable is an example of a mixin, like Comparable, Serializable or Persistent 07 December 2020 Object Oriented Design Course 47

Introductions: Compiler Warnings l l l Add a compile-time warning or error Issued if

Introductions: Compiler Warnings l l l Add a compile-time warning or error Issued if there is a chance that code will reach a given pointcut Warning / error string can be defined declare warning: Pointcut: String; declare error: Pointcut: String; The pointcuts must be statically determinable • Not allowed: this, target, args, if, cflowbelow 07 December 2020 Object Oriented Design Course 48

Example 10: Flexible Access Control l Control method access beyond private, protected and public

Example 10: Flexible Access Control l Control method access beyond private, protected and public declarations Violations must be found at compile time For example, class Product can only be initialized and configured by specific classes public class Product { public Product() { /* constructor implementation */ } public void configure() { /* configuration implementation */ } 07 December 2020 Object Oriented Design Course 49

Example 10: Flexible Access Control II l Use declare error to define access policy

Example 10: Flexible Access Control II l Use declare error to define access policy aspect Flag. Access. Violation { pointcut factory. Access. Violation() : call(Product. new(. . )) && !within(Product. Factory+); pointcut configurator. Access. Violation() : call(* Product. configure(. . )) && !within(Product. Configurator+); declare error : factory. Access. Violation() || configurator. Access. Violation() : "Access control violation"; } 07 December 2020 Object Oriented Design Course 50

Summary: The Syntax l l Pointcuts • • • call, execution, withincode, cflowbelow this,

Summary: The Syntax l l Pointcuts • • • call, execution, withincode, cflowbelow this, target, args, if this. Join. Point, this. Join. Point. Static. Part Advices • before, after (throwing & returning), around (proceed) Aspects • Fields & methods, Abstract aspects & pointcuts Introductions • • • Add fields, methods and constructor declare parents, declare soft declare error, declare warning 07 December 2020 Object Oriented Design Course 51

Summary: The Examples l l Development Time Examples • • • 1, 2: Tracing

Summary: The Examples l l Development Time Examples • • • 1, 2: Tracing - Printing “Debug Messages” 3: Contract enforcement 4: Profiling with fine-grained control 5: Pre- and post-conditions 10: Flexible method access control Production Time Examples • • 6: Resource pooling 7: Logging (of errors) 8: Modularizing functional guidelines 9: Implementing Mixins: Making classes Cloneable 07 December 2020 Object Oriented Design Course 52

Summary l AOP is a strong complement to OOD l Aspect. J is the

Summary l AOP is a strong complement to OOD l Aspect. J is the primary implementation today l A good tool, during development for now • Separation of concerns for unrelated aspects • Less code, more modular, easier to modify • Many practical uses, a lot of hype • Many features, good tools and active support • Yet the entire platform is still in ‘beta version’ 07 December 2020 Object Oriented Design Course 53

References http: //www. eclipse. org/aspectj/ l http: //www. eclipse. org/aspectj/doc/released l /progguide/starting-aspectj. html http:

References http: //www. eclipse. org/aspectj/ l http: //www. eclipse. org/aspectj/doc/released l /progguide/starting-aspectj. html http: //www. scribd. com/doc/81509801/Mast l ering-Aspectj-Aspect-Oriented. Programming-in-Java Examples: l http: //www. eclipse. org/aspectj/sample-code. html • http: //www. mkyong. com/spring 3/spring-aop-aspectj- • annotation-example/ 12/7/2020 Object Oriented Design Course 54