Aspect Oriented Programming Michael Kucera CAS 706 March

  • Slides: 38
Download presentation
Aspect Oriented Programming Michael Kucera CAS 706 March 15, 2005

Aspect Oriented Programming Michael Kucera CAS 706 March 15, 2005

Motivation for AOP • Typical programs often have behavior that doesn't fit into a

Motivation for AOP • Typical programs often have behavior that doesn't fit into a single module. • “Code Tangling” Accounting XML Parsing Logging Database

Crosscutting Concerns • AOP addresses behaviors that span many, often unrelated, modules. • Core

Crosscutting Concerns • AOP addresses behaviors that span many, often unrelated, modules. • Core Concerns: – Primary core functionality. – Central functionality of a module. • Crosscutting Concerns: – System wide concerns that span multiple modules. – Cuts across the typical division of responsibility. • OOP creates a coupling between core and crosscutting concerns. • AOP aims to modularize crosscutting concerns.

Aspects • In AOP crosscutting concerns are implemented in aspects instead of fusing them

Aspects • In AOP crosscutting concerns are implemented in aspects instead of fusing them into core modules. • Aspects are an additional unit of modularity. • Aspects can be reused. • By reducing code tangling it makes it easier to understand what the core functionality of a module is. • An “aspect weaver” takes the aspects and the core modules and composes the final system.

Aspect. J Example public class Example { public static void deliver. Message(String message) {

Aspect. J Example public class Example { public static void deliver. Message(String message) { System. out. println("The message is: " + message); } public static void main(String [] args) { deliver. Message("I'm here"); deliver. Message("Aspect. J rocks"); } } public aspect Example. Aspect { pointcut hello. PC() : call(void Example. deliver. Message(. . )); before() : hello. PC() { System. out. print("Hello! "); } after() : hello. PC() { System. out. println("The message has been delivered. "); } } Output: Hello! The message is: I'm here The message has been delivered. Hello! The message is: Aspect. J rocks The message has been delivered.

Weaving • Weaving rules specify how to integrate the final system. • Can be

Weaving • Weaving rules specify how to integrate the final system. • Can be implemented in various ways: – Source to source translation. – Bytecode enhancement, first compile source with original compiler, then weave aspects into class files. – Just-in-time weaving done by a classloader. – By the language compiler. • The JAs. Co language supports runtime weaving and unweaving.

Aspect. J – Overview • Join point – Places where crosscutting concerns can be

Aspect. J – Overview • Join point – Places where crosscutting concerns can be woven in. – Ex. method call, field access, object creation. • Pointcut – Declaration that selects join points and collects contexts at that point. • Advice – Code to be executed at a join point. – Three types: before, after and around. • Aspect – Unit of modularity. – Can contain fields and methods like a regular Java class.

Aspect. J – Overview • Introduction – Introduces changes to classes. – Makes static

Aspect. J – Overview • Introduction – Introduces changes to classes. – Makes static changes that alone do not effect be behavior of the system. – Can add methods and fields to a class. – Add implemented interfaces. – Adds mixin like inheritance to Java. • Compile time declaration – Add compile time errors and warnings upon detecting certain usage patterns. • Every valid Java program is a valid Aspect. J program.

Aspect. J – Join point model • Any identifiable execution point: – – –

Aspect. J – Join point model • Any identifiable execution point: – – – method body method call constructor body constructor call field access – – – catch block class (static) initialization object pre-initialization advice execution • All join points have a context. Certain pointcuts can capture the context and pass it to the advice.

Aspect. J – Capturing Context public class Employee { int salary; public void set.

Aspect. J – Capturing Context public class Employee { int salary; public void set. Salary(int salary) { this. salary = salary; } public static void main(String[] args) { Employee emp = new Employee(); emp. set. Salary(50000); System. out. println("Salary : " + emp. salary); } } public aspect Money. Aspect { pointcut employee. PC(int salary) : call(* Employee. set. Salary(. . )) && args(salary) ; void around(int salary) : employee. PC(salary) { salary *= 2; proceed(salary); } } Output: Salary: 100000

What about encapsulation? • AOP breaks encapsulation in a controlled manner. • Encapsulation is

What about encapsulation? • AOP breaks encapsulation in a controlled manner. • Encapsulation is broken between classes and aspects. • Aspects marked as privileged have access to the private members of a class. • Encapsulation is preserved between classes. • An aspect encapsulates a crosscutting concern.

Aspect. J - Pointcuts • Can be named or anonymous. • Named pointcuts: [access-specifier]

Aspect. J - Pointcuts • Can be named or anonymous. • Named pointcuts: [access-specifier] pointcut-name( [args] ) : pointcut-definition ; • The pointcut-definition part consists of anonymous pointcuts. • Anonymous pointcut used in advice definition: before() : call(* Account. *(. . )) {. . . advice body }

Aspect. J - Pointcuts • Pointcuts can use combinations of other pointcuts. pointcut employee.

Aspect. J - Pointcuts • Pointcuts can use combinations of other pointcuts. pointcut employee. Calls() : call(* Employee. *(. . )); pointcut internal. Operations() : employee. Calls() && within(banking. . *); • Wildcards can be used to capture join points that share common characteristics. * denotes any number of characters except a period. . denotes any number of characters + denotes any subclass of a given type • Can use operators &&, || and ! within a pointcut definition.

Aspect. J – Kinded pointcuts • Kinded pointcuts capture exposed join points. Join point

Aspect. J – Kinded pointcuts • Kinded pointcuts capture exposed join points. Join point category Pointcut syntax Method execution(Method. Signature) Method call(Method. Signature) Constructor execution(Constructor. Signature) Constructor call(Constructor. Signature) Class initialization staticinitialization(Type. Signature) Field read access get(Field. Signature) Field write access set(Field. Signature) Exception handler execution handler(Type. Signature) Object initialization(Constructor. Signature) Object pre-initialization preinitialization(Constructor. Signature) Advice execution adviceexecution()

Aspect. J – Control-flow based pointcuts • Capture all the join points within the

Aspect. J – Control-flow based pointcuts • Capture all the join points within the control flow of a join point. • cflow(call(* Account. debit(. . ))) – All the join points within the control flow of any debit method in the Account class, including the call to debit(). • cflowbelow(call(* Account. debit(. . ))) – Same as above but not including the call to debit(). • cflowbelow can be used to select non-recursive calls.

Aspect. J – Pointcuts that capture context • this() – the current object •

Aspect. J – Pointcuts that capture context • this() – the current object • target() – target object of a method call • args() – arguments passed to a method or constructor – exception caught by a handler join point – new value to be set in a field write access this. obj. do. Something(val) this() target() args()

Aspect. J – Advice • Advice is a method like construct that expresses the

Aspect. J – Advice • Advice is a method like construct that expresses the action to be taken at the join points that are captured by a pointcut. • Before advice – executes prior to the join point • After advice – executes following the join point • Around advice – surrounds the join point’s execution – can continue original execution, bypass execution or cause execution with an altered context – can cause execution of the join point multiple times

Aspect. J – Around advice public aspect Account. Aspect { void around(Account account, float

Aspect. J – Around advice public aspect Account. Aspect { void around(Account account, float amount) : call(* Account. withdraw(float)) && target(account) && args(amount) { System. out. println("Before withdrawl of amount: " + amount); if(amount > account. get. Balance()) System. out. println("Cannot make withdrawl"); else { proceed(account, amount); System. out. println("Withdrawl successful, balance: " + account. get. Balance()); } } }

Aspect. J – After advice • Executes after the execution of a join point.

Aspect. J – After advice • Executes after the execution of a join point. • Can distinguish between normal returns and those that throw an exception. after() returning : call(* Account. *(. . )) { System. out. println(“Successful return”); } after() throwing : call(* Account. *(. . )) { System. out. println(“Failure”); } after() throwing(Remote. Exception ex) : call(* *. *(. . )) { System. out. println(“Exception “ + ex + “ while executing “ + this. Join. Point); }

Aspect. J – Method result caching public class Factorial { public static long factorial(int

Aspect. J – Method result caching public class Factorial { public static long factorial(int n) { if(n == 0) return 1; return n * factorial(n - 1); } public static void main(String[] args) { System. out. println("Result : " + factorial(5)); } } public aspect Factorial. Optimize. Aspect { private Map cache = new Hash. Map(); pointcut factorial. Op(int n) : call(long *. factorial(int)) && args(n); long around(int n) : factorial. Op(n) { Object value = cache. get(new Integer(n)); if(value == null) return proceed(n); System. out. println(value + " retrieved from cache"); return ((Long)value). long. Value(); } after(int n) returning(long result) : factorial. Op(n) { if(cache. put(new Integer(n), new Long(result)) == null) System. out. println(result + " added to cache"); } } Output: 1 added to cache 2 added to cache 6 added to cache 24 added to cache 120 added to cache Result: 120 retrieved from cache Result: 120

Aspect. J – Aspects • Aspects can: – – – Include data members and

Aspect. J – Aspects • Aspects can: – – – Include data members and methods. Be declared abstract (won’t be weaved). Have access specifiers. Extend classes or aspects. Implement interfaces. • Aspects are not the same as classes: – Cannot be directly instantiated. – Cannot inherit from concrete aspects. – Can be marked as privileged.

Aspect. J – Abstract aspect example public abstract aspect Abstract. Logging { public pointcut

Aspect. J – Abstract aspect example public abstract aspect Abstract. Logging { public pointcut log. Points() : call(* *. *(. . )); public abstract Logger get. Logger(); before() : log. Points() { get. Logger(). log(Level. INFO, this. Join. Point. to. String()); } } public aspect Factorial. Logging. Aspect extends Abstract. Logging { // pointcut override public pointcut log. Points() : call(* *. factorial(. . )); public Logger get. Logger() { return Logger. global; } }

Static crosscutting • Dynamic crosscutting modifies the execution behavior of the program. • Static

Static crosscutting • Dynamic crosscutting modifies the execution behavior of the program. • Static crosscutting modifies the structure of the program. – – Member introduction. Type-hierarchy modification. Compile-time warning declaration. Exception softening. • Member introduction adds data members and methods to classes.

Introduction – Mixin style inheritance public interface Tagable { void set. Tag(String tag); String

Introduction – Mixin style inheritance public interface Tagable { void set. Tag(String tag); String get. Tag(); } public aspect Tag. Aspect { private String Tagable. tag; public String Tagable. get. Tag() { return tag; } public void Tagable. set. Tag(String tag) { this. tag = tag; } declare parents : Employee implements Tagable; before(Tagable t) : target(t) && !within(Tag. Aspect) { t. set. Tag(this. Join. Point. to. String()); } after(Tagable t) : target(t) && !within(Tag. Aspect){ System. out. println(t. get. Tag()); } }

Default interface implementation public interface Tagable { public void set. Tag(String tag); public String

Default interface implementation public interface Tagable { public void set. Tag(String tag); public String get. Tag(); static aspect Implementation { private String Tagable. tag; public void Tagable. set. Name(String tag) { this. tag = tag; } public String Tagable. get. Name() { return tag; } } } public class Example implements Tagable { public static void main(String[] args) { Example ex = new Example(); ex. set. Tag(”It works”); System. out. println(”Tag: ” + ex. get. Tag()); } }

Modifying the class hierarchy • Existing classes can be declared to implement an interface

Modifying the class hierarchy • Existing classes can be declared to implement an interface or extend a superclass. • Works as long as Java inheritance rules are not violated (no multiple inheritance). declare parents : [Type] implements [Interface. List]; declare parents : [Type] extends [Class]; • Aspects can be made dependant only on a base type or interface. This makes aspects more reusable.

Aspect. J – Exception softening • Converts a checked exception into a runtime exception.

Aspect. J – Exception softening • Converts a checked exception into a runtime exception. • Sometimes it can be inconvenient to have to deal with checked exceptions. Involves a proliferation of try/catch blocks and throws clauses. Example: SQLException in JDBC API declare soft : SQLException : within(Database. Access); • Exception is automatically rethrown as a org. aspectj. lang. Soft. Exception

Policy Enforcement • Mechanism for ensuring that system components follow certain programming practices. •

Policy Enforcement • Mechanism for ensuring that system components follow certain programming practices. • For example; enforce that public access to instance variables is prohibited. • Avoid incorrect usages of an API. • Ensures better quality. • In AOP policy enforcement concerns can be implemented in aspects. • Aspect based policy enforcement is reusable. • AOP can be used for “Design by Contract”.

Policy Enforcement in Aspect. J • Compile time and runtime enforcement. • In Aspect.

Policy Enforcement in Aspect. J • Compile time and runtime enforcement. • In Aspect. J it is possible to specify custom compile time warnings and errors using pointcuts. declare warning : get(* System. out) || get(* System. err) : “consider using Logger. log() instead”; declare error : set(public * *) || get(public * *) : “nonpublic access is not allowed”; • Runtime enforcement can be achieved through advice that detects policy violations.

Aspect precedence • It is possible for more than one piece of advice to

Aspect precedence • It is possible for more than one piece of advice to apply to a join point. • It may be important to control the order in which advice is applied. declare precedence : Aspect 1, Aspect 2, . . . ; • In the absence of any specified precedence control, the order in which the advice is applied is non-deterministic (at compile time). • If more than one piece of advice in the same aspect applies to a pointcut, then the advice that comes first in the file has precedence.

Aspect association • Typically an aspect represents a singleton object (aspect instance) that is

Aspect association • Typically an aspect represents a singleton object (aspect instance) that is instantiated by the system. • It may be useful to have more than one instance of an aspect in the system. Can create associations between aspect instances and other objects. • Can associate a new aspect instance with a target object by using a pointcut. public aspect Cache. Aspect perthis(access()) {. . } • Alternatively can use introduction.

CLOS – Method combination • Applicable generic methods are combined into a single effective

CLOS – Method combination • Applicable generic methods are combined into a single effective method. (defclass food () ()) (defclass pie (food) ()) (defmethod cook ((p pie)) (print "Cooking a pie. ")) (defmethod cook : before ((f food)) (print "A food is about to be cooked. ")) (defmethod cook : after ((f food)) (print "A food has been cooked. ")) (defmethod cook : before ((p pie)) (print "A pie is about to be cooked. ")) (defmethod cook : after ((p pie)) (print "A pie has been cooked. ")) (setq pie-1 (make-instance 'pie)) (cook pie-1) Output: A pie is about to be cooked A food is about to be cooked Cooking a pie A food has been cooked A pie has been cooked

JAs. Co – An aspect oriented language • Emphasizes aspect reuse. • In Aspect.

JAs. Co – An aspect oriented language • Emphasizes aspect reuse. • In Aspect. J pointcuts are hardcoded. . . less reuse. • JAs. Co allows adding, altering and removing aspects while the program is running. • Supports runtime weaving and unweaving. • Aspect beans: – Contain hooks: abstract pointcut definitions together with advice • Connectors: – used to deploy reusable aspect beans – explicitly specify the way aspect beans are combined

JAs. Co – Stateful aspects class Logger. Bean { hook Log. Hook { Log.

JAs. Co – Stateful aspects class Logger. Bean { hook Log. Hook { Log. Hook(startmethod(. . args 1), runningmethod(. . args 2), stopmethod(. . args 3)) { start > pc 1; pc 1: execution(startmethod) > pc 3 || pc 2; pc 3: execution(stopmethod) > pc 1; pc 2: execution(runningmethod) > pc 3 || pc 2; } before pc 2 (){ System. out. println(”executing: ” + calledmethod. get. Name()); } } } static connector testconnector { Logger. Bean. Log. Hook hook 1 = new Logger. Bean. Log. Hook(* *. *. start(*), * *. do. It(*), * *. *. stop(*)); Logger. Bean. Log. Hook hook 2 = new Logger. Bean. Log. Hook(* *. *. login(*), * *. shop(*), * *. *. logout(*)); hook 1. before(); hook 2. before(); } // optional

Case study – JDO • JDO (Java Data Objects) is a “transparent persistence” framework

Case study – JDO • JDO (Java Data Objects) is a “transparent persistence” framework for Java. • Allows the manipulation of the state of an object to transparently update a database. Employee public class Employee { string name; int salary; } fred. salary = 200; Name Salary Fred 100 200 Biff 150 causes transparent update

Case study – JDO • Uses advice to add side effects to field access.

Case study – JDO • Uses advice to add side effects to field access. • Weaving is done by the JDO bytecode enhancer. Employee. javac Employee. class mapping. xml JDO bytecode enhancer (Aspect weaver) enhanced Employee. class

Conclusion • • • AOP has many potential benefits. Higher modularization. Cleaner responsibilities for

Conclusion • • • AOP has many potential benefits. Higher modularization. Cleaner responsibilities for individual modules. Improved separation of concerns. Easier system evolution. Much easier to add crosscutting functionality. More code reuse. Can make code easier or harder to understand. Already starting to become mainstream (JBoss, JDO, Spring). Like any new technology, AOP can be abused.

References • • • Laddad, Ramnivas. Aspect. J in Action. Greenwich, Conn. : Manning

References • • • Laddad, Ramnivas. Aspect. J in Action. Greenwich, Conn. : Manning Publications, 2003. Lesiecki, Nicholas. “Improve modularity with aspect oriented programming”. IBM Developerworks, January, 2002. Available online at http: //www 106. ibm. com/developerworks/java/library/j-aspectj. Marshall, Joe. “Warp Speed Introduction to CLOS”. Available online at http: //home. comcast. net/~prunesquallor/guide. html. Vanderperren, W. , Suvee, D. , Cibran, M. and De Fraine, B. Stateful Aspects in JAs. Co. In proceedings of SC 2005, LNCS, April 2005 Eclipse Aspect. J plug-in, http: //eclipse. org/aspectj.