a first language for aspect-oriented programming

41
Overview of AspectJ A first language for Aspect-Oriented Programming Based on slides by Oren Mishali

Upload: gavin-mclaughlin

Post on 18-Jan-2018

229 views

Category:

Documents


0 download

DESCRIPTION

Aspect Oriented Programming A reminder… During the life cycle of a software system, we encounter crosscutting concerns that span multiple modules. e.g. tracing, caching … Attempt to implement them in a traditional way (OOP) leads to scattering & tangling. AOP suggests the separation of each concern into unit of modularization – aspect.

TRANSCRIPT

Page 1: A first language for Aspect-Oriented Programming

Overview of AspectJ

A first language for Aspect-Oriented Programming

Based on slides byOren Mishali

Page 2: A first language for Aspect-Oriented Programming

Aspect Oriented Programming A reminder…

During the life cycle of a software system, we encounter crosscutting concerns that span multiple modules.

e.g. tracing, caching … Attempt to implement them in a traditional way (OOP) leads to scattering & tangling. AOP suggests the separation of each concern into unit of modularization – aspect.

Page 3: A first language for Aspect-Oriented Programming

Pointcuts and Advice Most of AspectJ gives keywords for

defining joinpoints within pointcuts (Where and When)

Advice (What) is slightly extended Java Pointcuts are also used to expose

context from the joinpoint environment to the advice code

Page 4: A first language for Aspect-Oriented Programming

A simple banking system

While developing , we want to trace each public method call. Solution without AspectJ:

Look for public method calls and insert printing before the call.

Account-

balance:float+deposit(float)+withdraw(float)

Client

Clerk*

*<< uses >>

Page 5: A first language for Aspect-Oriented Programming

AspectJ solution

aspect PublicTracing { pointcut publicCalls() :

call ( public *.* (..) );

before() : publicCalls() {System.out.println(“Calling public method”);

}}

PublicTracing.java

ajc *.java java BankingSystemCalling public methodCalling public method… … … … … … …

Page 6: A first language for Aspect-Oriented Programming

AspectJ

General-purpose, aspect oriented extension to Java.

Every valid Java program is also a valid AspectJ program.

With AspectJ: You implement the core concerns using Java. You use the extensions provided to implement the aspects. You weave them together with ajc (no need for javac).

New versions are frequent (now 1.5.2)

Page 7: A first language for Aspect-Oriented Programming

Dynamic crosscutting

AspectJ enables us to define events in the program flow and then add an advice at those events. This capability is called dynamic crosscutting Keywords: join point, pointcut, advice.

Is it possible to add an advice before the execution of a while block ?

Or before the execution of a method?

Page 8: A first language for Aspect-Oriented Programming

Join points Join point is an event in the execution of a program.

With well defined start point and end point.e.g. execution of a for block, method call, static initialization of a class, execution of a catch block …

Exposed join points are subset of all possible join pointsthat AspectJ exposes to us.

In practice this means that we can only add advice at exposed join points.

So what are they?

Page 9: A first language for Aspect-Oriented Programming

Exposed join points in AspectJMethod call & Method execution

acount.deposit(amount)

:Client account:Account

deposit execution

deposit call

The most useful join points. For most purposes, the difference does not matter. What is the difference?

deposit(amount)

Page 10: A first language for Aspect-Oriented Programming

Exposed join points in AspectJAll the rest…

Constructor call & execution

Field read & write access ( Except for local or const )

Execution of a catch block

Static initialization of a class

Object initialization & pre-initialization

Execution of an advice ( Advise an advice ? )

Is it possible to add an advice before the

execution of a while block ?

Page 11: A first language for Aspect-Oriented Programming

Pointcuts

Join point is a concept. Pointcut is a syntactic construct that defines a set of join

points. Suppose we want to trace each execution of a catch block that

handles exceptions of type AccountException:before() : handler(AccountException) { System.out.println(“Before execution of catch block”);}

Or:pointcut accountExceptionHandler() : handler(AccountException);

before() : accountExceptionHandler() { System.out.println(“Before execution of catch block”);}

Anonymous pointcut

Named pointcut

Page 12: A first language for Aspect-Oriented Programming

Pointcuts (cont.) In same manner, a pointcut syntax exists for each kind

of join point. E.g. call( pattern ), execution( pattern ), set( pattern ) … Use * , + , .. wildcards to define a common pattern.

Use operators to create complex pointcuts: ! p - each join point that is not defined by pointcut p. p1 || p2 – each join point that is defined by either p1 or p2. p1 && p2 – each join point that is defined by both p1 and p2.

E.g.set(private float Account.balance) && get(private float

Account.balance)set(private float Account.balance) || get(private float

Account.balance)

Page 13: A first language for Aspect-Oriented Programming

More primitive pointcuts…

Some join points have arguments: Method and constructor join points. Execution of a catch block ( handled exception ). Field write access ( new value to be set ).

Suppose we want to trace each join point that has one argument of type String.

We can do that using args( pattern ) primitive pointcut:

before() : args( String ) {System.out.println( “Before one String parameter”);

}

Page 14: A first language for Aspect-Oriented Programming

More primitive pointcuts…

Suppose we want to trace each call to Account.deposit(float) made by a Clerk object but not by a Client object.

call( public void Account.deposit(float) ) ?

this( Type ) pointcut defines all join points where this-object is subtype of Type including Type itself.

before() : call( public void Account.deposit(float) ) && this ( Clerk ) {System.out.println( “Clerk object calls Account.deposit()” );

}

target( Type ) is similar but based on the target object.

call( * Account+.*(..) ) == target( Account ) ?

Page 15: A first language for Aspect-Oriented Programming

Scoping pointcuts adviceexecution() –all joinpoints in

advice within(TypePattern) –all joinpoints in

code defined in the Type (class or aspect)

withincode(MethodPattern) –every joinpoint within methods with MethodPattern signature

Page 16: A first language for Aspect-Oriented Programming

Passing context from join point to advice

Advice often needs some information about the advised join point. (context)

E.g. advice on a method call join point wants to print the caller object (this), the called object (target), or the method arguments.

A pointcut may expose an argument/this-object/target-

object from a join point.

pointcut withdrawOperations(Client client, Account account, float amount) :call( public void Account.withdraw( float ) ) && this( client )&& target( account ) && args( amount ) ;

Page 17: A first language for Aspect-Oriented Programming

Advicebefore() advice

Logic - permit withdraw only if account.balance >= amount.

before( Client client, Account account, float amount ) throws

AccountException : withdrawOperations( client, account, amount ) {

if ( account.balance() < amount ) {client.send(“Please contact you bank office”);account.block(true);throw new AccountException();

}}

Note parameters of the before that link pointcut arguments withthe advice

Page 18: A first language for Aspect-Oriented Programming

Advicearound() advice

Logic – if amount > account.balance, withdraw balance.

void around( Client client, Account account, float amount ) throws AccountException: withdrawOperations( client, account, amount) {if ( amount < account.balance() )proceed( client, account, amount);elseproceed( client, account, account.balance() );

}

around() advice executes instead of the join point. You must specify a return value.

Page 19: A first language for Aspect-Oriented Programming

Adviceafter() advice

Several kinds of after() advice: after returning() – executes only after a successful return. after throwing() – executes only after thrown exception. after() – executes after both cases.

We can access the return value / exception :after() returning(float amount) : call( Account.balance(..) ) {Logger.log(amount);}

Page 20: A first language for Aspect-Oriented Programming

Aspect Is the basic unit of modularization for crosscutting concern in

AspectJ. Can includes advice, pointcuts, introductions and compile-time

declarations. An aspect is like a class:

Can include data members and methods. Can have access specifier. Can be declared as abstract. Can be embedded inside classes and interfaces.

An aspect is not a class: Cannot be directly instantiated with new.

Instantiation is done by the system. Singleton by default. Cannot inherit from concrete aspects. Can have a privileged access specifier.

Gives it access to the private member of the class it is crosscutting.

Page 21: A first language for Aspect-Oriented Programming

Static crosscutting Modifies the static structure of the program or its

compile-time behavior.

Member introduction. Adding class fields or methods.

Type-hierarchy modification. Adding class interfaces or a super class.

Compile-time errors and warnings. Based on certain usage patterns.

Page 22: A first language for Aspect-Oriented Programming

Static crosscuttingMember introduction

Suppose we want to allow deposit only if it is higher than last deposit.

We need lastDeposit field. Where?

aspect DepositAspect { private float Account.lastDeposit = 0; // private to the aspect,

not to Account.void around( Account account, float amount ) : execution ( void Account.deposit(float) ) && args( amount ) &&this(account) {

if ( amount > account.lastDeposit ) {proceed( account, amount );account.lastDeposit = amount;

}}

}

Page 23: A first language for Aspect-Oriented Programming

More on AspectJ:cflow() and cflowbelow() pointcuts

:Client :Account

:Database

withdraw(amount) confirm(amoun

t)

Account.withdraw( amount ) The program fails in the marked area. should we trace using execution(Database.confirm(float)) ? cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. cflowbelow( pointcut )Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points.

Page 24: A first language for Aspect-Oriented Programming

More on AspectJ:clflow() & cflowbelow() pointcuts

:Client :Account

:Database

withdraw(amount) confirm(amoun

t)

Account.withdraw( amount ) The program fails in the marked area. should we trace using execution(Database.confirm(float)) ? cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. cflowbelow( pointcut )Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points.

cflow( call(Account.withdraw(float)) && this(Client) )

Page 25: A first language for Aspect-Oriented Programming

More on AspectJ:clflow() & cflowbelow() pointcuts

:Client :Account

:Database

withdraw(amount) confirm(amoun

t)

Account.withdraw( amount ) The program fails in the marked area. should we trace using execution(Database.confirm(float)) ? cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. cflowbelow( pointcut )Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points.

cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) )

Page 26: A first language for Aspect-Oriented Programming

More on AspectJ: clflow() & cflowbelow() pointcuts

:Client :Account

:Database

withdraw(amount) confirm(amoun

t)

Account.withdraw( amount )

cflowbelow( call(Account.withdraw(float)) && this(Client) )

The program fails in the marked area. should we trace using execution(Database.confirm(float)) ? cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. cflowbelow( pointcut )Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points.

cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) )

Page 27: A first language for Aspect-Oriented Programming

More on AspectJ clflow() & cflowbelow() pointcuts

:Client :Account

:Database

withdraw(amount) confirm(amoun

t)

Account.withdraw( amount ) The program fails in the marked area. should we trace using execution(Database.confirm(float)) ? cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. cflowbelow( pointcut )Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. cflowbelow( call(Account.withdraw(float)) && this(Client) )

&& execution(Database.confirm(float))

cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) )

Page 28: A first language for Aspect-Oriented Programming

More on AspectJthisJoinPoint

Special reference variable that contains static and dynamic information of a join point.

May be used by an advice. Usage involves run-time creation overhead.

Use thisJoinPointStaticPart when only static information is necessary.

When possible, prefer usage of args() this() and target() to collect dynamic information.

Page 29: A first language for Aspect-Oriented Programming

More on AspectJAdvice precedence

Often, several advices may advise the same join point in the same place.

What is the order of execution?

Precedence of such advices in a single aspect is according to their lexical appearance.

declare precedence construct should be used when order of execution is important among different aspects.

declare precedence : FirstAspect , SecondAspect; specifies that advices of FirstAspect take higher precedence.

Page 30: A first language for Aspect-Oriented Programming

Contract Enforcement Design by contract.

Precondition defines the client's responsibility.

Postcondition is the supplier's part of the contract.

Putting pre- and post-condition assertions directly into application code? Lack of code modularity. Tangled code. Mixes

business-logic code with assertions.

Page 31: A first language for Aspect-Oriented Programming

Contract Enforcement - Example

class Point {int _x, _y;void setX(int x) { _x = x; } // precondition: x >= MIN_Xvoid setY(int y) { _y = y; }int getX() { return _x; }int getY() { return _y; }

}

class Client { Client(Point p) {

p.setX(-1); p.setY(50); // postcondition: p.getY() ==

50 }}

Page 32: A first language for Aspect-Oriented Programming

Pre-ConditionUsing Before Advice

aspect PointBoundsPreCondition {before(int newX):call(void Point.setX(int)) && args(newX) {

assert(newX >= MIN_X);assert(newX <= MAX_X);

}

before(int newY): call(void Point.setY(int)) && args(newY){assert(newY >= MIN_Y);assert(newY <= MAX_Y);

}private void assert(boolean v) {

if ( !v ) throw new RuntimeException();

}}

Page 33: A first language for Aspect-Oriented Programming

Post-ConditionUsing After Advice

aspect PointBoundsPostCondition {after(Point p, int newX) returning:

call(void Point.setX(int)) && target(p) && args(newX) {

assert(p.getX() == newX);}after(Point p, int newY) returning:

call(void Point.setY(int)) && target(p) && args(newY) {

assert(p.getY() == newY);}private void assert(boolean v) {

if ( !v ) throw new RuntimeException();

}}

Page 34: A first language for Aspect-Oriented Programming

Flexible Access Control Enforce an access-control crosscutting concern. Java's access controls: public, private, package, and

protected. Not enough control in many cases. Example: Factory design-pattern implementation:

We want only the factory to create the product objects. Other classes should be prohibited from accessing

constructors of any product class. Marking constructors with package access? Only when the factory resides in the same package as the

manufactured classes - inflexible solution!

Page 35: A first language for Aspect-Oriented Programming

Flexible Access Control (continued) C++'s friend mechanism controls access to a class from other

specified classes and methods. With AspectJ we can implement such functionality in Java. Even more fine-grained and expressive access control!

Page 36: A first language for Aspect-Oriented Programming

Flexible Access Control - Example Product class has a constructor and a configure() method. We also declare a nested FlagAccessViolation aspect. Pointcut 1 detects constructor calls not from ProductFactory or its

subclasses. Pointcut 2 detects configure() calls not from ProductConfigurator or its

subclasses. We declare either such violations as compile-time errors.

public class Product {public Product() { /* constructor implementation */ }public void configure() { /* configuration implementation */ }

static aspect FlagAccessViolation { pointcut factoryAccessViolation()

: call(Product.new(..)) && !within(ProductFactory+);             pointcut configuratorAccessViolation()         : call(* Product.configure(..)) && !within(ProductConfigurator+);

     declare error         :  factoryAccessViolation() ||

configuratorAccessViolation()         : "Access control violation";    }}

must be a “static pointcut”

If any of the join points in the pointcut possibly exist in the program, the compiler should emit an error of String.

Page 37: A first language for Aspect-Oriented Programming

Flexible Access Control - Examplepublic class ProductFactory {

    public Product createProduct() {        return new Product(); // ok    }        public void configureProduct(Product product) {        product.configure(); // error     }}

The ProductFactory class calls the Product.configure() method.

Compile-time error with a specified "Access control violation" message.

Page 38: A first language for Aspect-Oriented Programming

Semantic based crosscutting behaviorProblem:

Operations with the same semantic characteristics should typically implement common behaviors.

A wait cursor should be put before any slow method executes. Authentication before access to all security-critical data.

Since such concerns possess a crosscutting nature, AOP and AspectJ offer mechanisms to modularize them.

Because a method's name might not indicate its characteristics, we need a different mechanism to capture such methods.

Page 39: A first language for Aspect-Oriented Programming

Semantic based crosscutting behaviorSolution:

Declare the aspect adding semantic-based crosscutting behavior as an abstract aspect.

In that aspect, declare an abstract pointcut for methods with characteristics under consideration.

Finally, write an advice performing the required implementation.

Page 40: A first language for Aspect-Oriented Programming

Semantic based crosscutting behaviorExample: SlowMethodAspect declares the abstract slowMethods() pointcut

and advises it to first put a wait cursor, proceed with the original operation, and finally restore the original cursor.

Page 41: A first language for Aspect-Oriented Programming

Semantic based crosscutting behaviorImplementation:public abstract aspect SlowMethodAspect {

    abstract pointcut slowMethods(Component uiComp);

    void around(Component uiComp) : slowMethods(uiComp) {        Cursor originalCursor = uiComp.getCursor();        Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);        uiComp.setCursor(waitCursor);

        try {            proceed(uiComp);        } finally {            uiComp.setCursor(originalCursor);        }    }}

GUIComp1 contains following aspect: public static aspect SlowMethodsParticipant extends SlowMethodAspect {

pointcut slowMethods(Component uiComp)             : execution(void GUIComp1.performOperation1())            && this(uiComp);}

The aspected classes include code to participate

in the collaboration