Aspect-Oriented Programming with AspectJ Using slides from Jorrit N. Herder ( [email protected]...

87
Aspect-Oriented Aspect-Oriented Programming Programming with AspectJ with AspectJ Using slides from Jorrit N. Herder ( [email protected] ) Mik Kersten ( aspectj.org Palo Alto Research Center )

Transcript of Aspect-Oriented Programming with AspectJ Using slides from Jorrit N. Herder ( [email protected]...

Aspect-Oriented ProgrammingAspect-Oriented Programmingwith AspectJwith AspectJ

Using slides fromJorrit N. Herder ( [email protected] )

Mik Kersten ( aspectj.org Palo Alto Research Center )

good modularitygood modularity

• XML parsing in org.apache.tomcat– red shows relevant lines of code– nicely fits in one box

XML parsing

good modularitygood modularity

• URL pattern matching in org.apache.tomcat– red shows relevant lines of code– nicely fits in two boxes (using inheritance)

URL pattern matching

good modularitygood modularity

• socket creation in Tomcat– colored lines show relevant lines of code– fits nicely into one package (3 classes)

pretty good modularitypretty good modularity

• class loading in Tomcat– colored lines show relevant lines of code– mostly in one package (9 classes)

not so good modularitynot so good modularity

• logging in Tomcat– scattered across the packages and classes– error handling, security, business rules, …

logging, zoomed inlogging, zoomed in

//From ContextManager

public void service( Request rrequest, Response rresponse ) { // log( "New request " + rrequest ); try { // System.out.print("A"); rrequest.setContextManager( this ); rrequest.setResponse(rresponse); rresponse.setRequest(rrequest);

// wront request - parsing error int status=rresponse.getStatus();

if( status < 400 ) status= processRequest( rrequest );

if(status==0) status=authenticate( rrequest, rresponse ); if(status == 0) status=authorize( rrequest, rresponse ); if( status == 0 ) { rrequest.getWrapper().handleRequest(rrequest, rresponse); } else { // something went wrong handleError( rrequest, rresponse, null, status ); } } catch (Throwable t) { handleError( rrequest, rresponse, t, 0 ); } // System.out.print("B"); try { rresponse.finish(); rrequest.recycle(); rresponse.recycle(); } catch( Throwable ex ) { if(debug>0) log( "Error closing request " + ex); } // log( "Done with request " + rrequest ); // System.out.print("C"); return;}

// log( "New request " + rrequest );

// System.out.print(“A”);

// System.out.print("B");

// log("Done with request " + rrequest);

if(debug>0) log("Error closing request " + ex);

// System.out.print("C");

Without AOPWithout AOP

With AOPWith AOP

Code tangling Code scattering

Code tangling Code scattering

the cost of tangled codethe cost of tangled code

• redundant code– same fragment of code in many places

• difficult to reason about– non-explicit structure– the big picture of the tangling isn’t clear

• difficult to change– have to find all the code involved– and be sure to change it consistently

Cross Cutting ConcernCross Cutting Concern

• What is a crosscutting concern?

– 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.

the aop ideathe aop idea

• crosscutting is inherent in complex systems

• crosscutting concerns– have a clear purpose

– have a natural structure

• so, let’s capture the structure of crosscutting concerns explicitly...– in a modular way

– with linguistic and tool support

• aspects are– well-modularized crosscutting concerns

AspectJ HistoryAspectJ History

• Java with Aspects• Developed at Xerox PARC (Palo Alto RC)• Launched in 1998• PARC transferred AspectJ to an openly-

developed eclipse.org project in December of 2002.

For more info: www.eclipse.org/aspectj

TerminologyTerminology

• Cross-cutting – Identify areas of code where common functionality exists

• Advice – The code to be injected

• Joinpoint – Where one or more aspects can be applied

• Pointcut – A collection of joinpoints

• Aspect – General term for where advice and point-cuts are combined

TerminologyTerminology

• Weaving – Integrating applications and aspects (e.g. AspectJ is an “aspect weaver”)

– Compile-time – Can produce integrated source-code, but typically only produces woven byte-code.

– Run-time – Aspects are applied “on the fly” (typically when classes are loaded)

package com.aspect;

public aspect DemoAspect {

pointcut setterNotification() : call(* *.set*(..));

before() : setterNotification(){System.out.println("setting data...");

}

}

Quick LookQuick Look

Point-cut

Advice

Aspect

Language: Join PointsLanguage: Join Points

• Well-defined points in the execution of a program:– Method call, Method execution– Constructor call, Constructor execution– Static initializer execution – Object pre-initialization, Object initialization– Field reference, Field set– Handler execution– Advice execution

Joinpoint TypesJoinpoint Types

• call(method expr)– when a method is called

• execution(method expr)– when a method is executed

• handler(exception expr)– when a catch block is executed

Defining JoinpointsDefining Joinpoints

//call is the most common joinpoint type

call([access modifier] returnType package.ClassName.method(args));

//Examples

call(* *.*(..)); //Note: “..” is also a wildcard

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

call(void *.set*(..));

call(* *.set*(int));

call(String com.foo.Customer.set*(..));

call(* com.foo.Customer+.set*(..)); //”+” cross-cuts children

call(public void com..*.set*(int));

call(* *.set*(int, ..));

call(* *.set*(int, .., String));

Joinpoint TypesJoinpoint Types

• get(field expr)– when a field is read

• set(field expr)– when a field is set

• staticinitialization(class expr)– when a static block of a class is exectued

Joinpoint TypesJoinpoint Types

• initialization(constructor expr)– when a constructor is executed

• preinitialization(constructor expr)– when inherited constructors are executed

• adviceexecution()– when an advice block is executed

Language: PointcutsLanguage: Pointcuts

• A set of join point, plus, optionally, some of the values in the execution context of those join points.

• Can be composed using boolean operators || , &&

• Matched at runtime

Defining PointcutsDefining Pointcuts

public aspect SomeAspect{

pointcut uberPointCut() : call(* *.*(..));

pointcut setterTrace() : call(* *.set*(int, ..));

pointcut exceptionTrace() : handler( java.io.Exception+ );

}

• Defining a pointcut is similar to defining a method• Define the pointcut name and the joinpoint

type/expression

Defining AdviceDefining Advice

pointcut somePointCut() :

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

before() : somePointCut(){

System.out.println("Injecting advice...");

}

after() : somePointCut(){

System.out.println("Advice injected");

}

• Advice, is even more similar to defining a method

Defining AdviceDefining Advice

//NOTE: You can streamline your definition of a

// joinpoint and advice.

before() : call(* *.*(..)) {

System.out.println("Injecting advice...");

}

//vs.

before() : somePointCut(){

System.out.println("Injecting advice...");

}

Advice TypesAdvice Types

• before()• after() returning• after() throwing• after()• around()

Talk outlineTalk outline

• OOP benefits and shortcomings

• Different kinds of software properties• What is AOP and what are the benefits?• How does AOP actually work?• An example application in AspectJ• Design Patterns and AOP

OOP benefitsOOP benefits

• OOP builds on existing paradigms

• Elegant programming solutions– Inheritance (specialized classes)– Dynamic binding (polymorphic behavior)

• Maintenance becomes easier– Object model is rather stable

• Reuse of components is easy• OOAD can be used as design method

OOP shortcomingsOOP shortcomings

• OOP allows to decompose a system into units of function or behavior

• Certain software properties cannot be isolated in single functional unit, instead they crosscut multiple components

• Such crosscutting concerns result in tangled code that is hard to develop and maintain

Software properties (1/2)Software properties (1/2)

• Components: properties that can be cleanly encapsulated in a unit of function or behavior; like a procedure or object

• Aspects: cross-cutting concerns that cannot be captured in a functional decomposition; properties affecting the performance or semantics of components

Software properties (2/2)Software properties (2/2)

• Components– GUI elements– Readers and writers– Database

• Aspects– Debugging– Logging– Synchronization

Aspect-Oriented ProgrammingAspect-Oriented Programming

• Definition: ''... to support the programmer in cleanly separating components and aspects from each other, by providing mechanisms that allow to abstract and compose them to produce the overal system.''

AOP BenefitsAOP Benefits

• All benefits of OOP discussed before• Separation of components and aspects

– Better understanding of software because of high level of abstraction

– Easier development and maintenance because tangling of code is prevented

– Increased potential for reuse for both components as well as aspects

How does AOP work?How does AOP work?

AOP InfrastructureAOP Infrastructure

Cross Cross Cutting Cutting ConcernsConcerns

AOP mechanismsAOP mechanisms

• Abstraction mechanism: An aspect description language is used to encapsulate crosscutting concerns into modules according to the join point model

• Composition mechanism:A weaver is used to merge the aspects and components into an application that only contains traditional language constructs

Join point model (1/2)Join point model (1/2)

• Identify “join points”– Points in the execution of components where

aspects should be applied– E.g method invocation or object construction– Use “Pointcuts” to collect sets of join points

• Describe “Advice”, behavior at join points– Wrap join points with extra code before,

after execution… in place of, or added to

Join point model (2/2)Join point model (2/2)

• A method call join point:

aspect PublicErrorLogging {

Log log = new Log();

pointcut publicInterface (): call(public * org.apache.tomcat..*.*(..));

after() throwing (Error e): publicInterface() { log.write(e); }}

logging, modularizedlogging, modularized

• crosscutting concerns– tangled implementation complex, difficult to maintain

– modular implementation can be clear, easy to maintain

• crosscutting concerns per se not complicated!

captures public interface of tomcat package

WeavingWeaving

• Aspect description languages cannot be processed by tradional compilers

• Therefore, aspects and components are woven into intermediate source code

• Weaving is no longer needed if there is an aspect-oriented compiler available

• This can be compared to preprocessing of C++ code to generate a C representation

Illustration of AOPIllustration of AOP

• The concepts presented will now be illustrated by an example application in the aspect-oriented language AspectJ

• Any questions so far?

AspectJAspectJ

• Is a general-purpose aspect-oriented extension to Java, which is freely available from http://www.aspectj.org/

• Java: defines components as before • by encapsulating data and behavior in objects

• AspectJ: defines aspect modules• by describing join points and behavior

PausePause

a simple figure editora simple figure editor

operations that move elements

factory methodsDisplay

*

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)

Figure

makePoint(..)makeLine(..)

FigureElement

moveBy(int, int)

a Line

a Point

join pointsjoin points

returning or throwing

dispatch

dispatch

key points in the dynamiccall graph

a method call

returning or throwinga method execution

returning or throwinga method execution

imagine l.move(2, 2)

join point terminologyjoin point terminology

• several kinds of join points– method & constructor execution

– method & constructor call

– field get & set

– exception handler execution

– static & dynamic initialization

a Line

dispatch

method call join points

method execution join points

pointcuts: naming join pointspointcuts: naming join pointseach execution of the <void Line.setP1(Point)> or <void Line.setP2(Point)> method

or

a “void Line.setP2(Point)” execution

name and parametersa “void Line.setP1(Point)” execution

pointcut move(): execution(void Line.setP1(Point)) || execution(void Line.setP2(Point));

pointcut move(): execution(void Line.setP1(Point)) || execution(void Line.setP2(Point));

after() returning: move() { <code here runs after each move> }

advice: action under joinpointsadvice: action under joinpoints

a Line

after advice runs“on the way back out”

a simple aspecta simple aspect

aspect HistoryUpdating { pointcut move(): exucution(void Line.setP1(Point)) || execution(void Line.setP2(Point));

after() returning: move() { <code here runs after each move> }}

an aspect defines a special class that can crosscut other classes

Problem descriptionProblem description

• Question: ''How to enforce synchronization policies with AOP?''

• Suppose multiple objects are concurrently working on some shared data and exclusive access is needed for modification

• All objects that are working on the data must be synchronized, for example by locking the shared data temporarily

interface Observer {

/* ... the observer design pattern requires that every observer implements this interface ...*/

public void update(Subject s);}

class ConcreteObserver implements Observer { ... public void update(Subject s) { // ... get new state from the subject } ...}

class SharedData {

/* ... apply singleton design pattern ... */

private SharedData instance;

private SharedData() { // ... initialize shared data object } public static SharedData getInstance() { if (instance == null) instance = new SharedData(); return instance; } ...}

class Worker extends Thread {

/* ... multithreading allows concurrent access ... */

private SharedData data = SharedData.getInstance();

public void modify() { /* modify data */ // ... needs exclusive access! } public void run() { /* start thread */ // ... schedule actions to modify() // ... according to external circumstances } ... ...}

Problem analysisProblem analysis

• Synchronization is a crosscutting concern that affects all components that are working on the shared data

• Components: readers, writers, and data• Aspect: the locking literally cross-cuts all

components that are working on the data

ObservationObservation

• Without AOP– Every component that works on the shared

data must take care of the locking itself, leading to tangled and complex code

• With AOP– The locking aspect is separated from the

components by means of an aspect module, resulting in usual benefits of modularization

aspect ExclusiveAccess {

private boolean locked; /* private to aspect */

pointcut access(): /* method call join point */ call( void Worker.modify() ) ;

before(Worker worker) : access() && this(worker) { while( ! acquireLock() ) { /* synchronization point */ try { worker.sleep(); } catch(InterruptedException e) { } } }

// ... rest of aspect ExclusiveAccess

after() : access() { releaseLock(); /* nothing special */ }

private synchronized boolean acquireLock() { if (locked) return false; locked = true; return locked; }

private void releaseLock() { locked = false; }}

Conclusions sofar ...Conclusions sofar ...

• Today's programming languages have problems capturing cross-cuttings

• AOP languages, like AspectJ, provide mechanisms to cleanly abstract from components and aspects

• Improved modularity allows simpler code that is easier to develop and maintain, and that has greater potential for reuse

Design PatternsDesign Patterns

• Design patterns are proven solutions that provide elegant ways for solving frequently occuring problems

• Effects of AOP on design patterns were studied by analysing Java and AspectJ implementations of Observer, Composite, Visitor, Proxy, Decorator

ObservationsObservations

1. Existing design patterns may be replaced by aspect-oriented patterns that provide a different solution for the same problem

2. Existing object-oriented design patterns may be implemented more modular with aspect-oriented technologies

AspectJ constructsAspectJ constructs

• Assigning roles to participants– declare parents: Participant implements Role;

• Attaching pattern functionality– public void Node.accept(Visitor v) {

v.visit(this)}

• Event handling (join points + advice)– abstract pointcut event(Subject s);

– after(Subject s): event(s) { ... notify observers ... }

ObserverObserver

• GoF: ''Define one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.''

– Decouple components– Retain a consistent state

abstract aspect ObserverProtocol {

protected interface Subject {} /* defines role */ protected interface Observer {} /* defines role */

private WeakHashMap perSubjectObservers;

public void addObserver(Subject s, Observer o) { // ... register observer o of subject s getObservers(s).add(o); } public void removeObserver(Subject s, Observer o) { getObservers(s).remove(o); }

...

// ... rest of aspect ObserverProtocol

/* abstract join points after which to do update */ protected abstract poincut subjectChange(Subject s);

/* abstract method that does actual observer update */ protected abstract void update(Subject s, Observer o);

/* abstract method that does actual observer update */ after(Subject s): subjectChange(s) { Iterator i = getObservers(s).iterator(); while (i.hasNext() ) { update( s, ((Observer) i.next()) ); } }}

aspect ColorObserver extends ObserverProtocol {

/* superimpose roles on participating classes */ declare parents: Points implements Subject; declare parents: Screen implements Observer;

/* concretize abstract join points of interest */ protected pointcut subjectChange(Subject s): call(void Point.setColor(Color) && target(s);

/* concretize behavior if event occurs */ protected void update(Subject s, Observer o) { ((Screen) o).display(''Color changed, screen updated''); }}

VisitorVisitor

• GoF: ''Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.''

– Node classes independent of operations– Easily define new operations

abstract aspect VisitorProtocol {

/* define roles for elements in object structure */ public interface VisitorNode {} protected interface VRegularNode extends VisitorNode {}

protected interface VLeafNode extends VisitorNode {}

/* role interface to be implemented by concrete visitors */ public interface NodeVisitor { // ... call-back methods for concrete visitors public void visitRegularNode(VisitorNode node); public void visitLeafNode(VisitorNode node); } ...

// ... rest of aspect VisitorProtocol

/* attachment of the double-dispatch protocol */ public void VisitorNode.accept(NodeVisitor v) {}

public void VRegularNode.accept(NodeVisitor v) { v.visitRegularNode(this); } public void VLeafNode.accept(NodeVisitor v) { v.visitLeafNode(this); } }

aspect ConcreteVisitor extends VisitorProtocol {

/* superimpose roles on participating classes */ declare parents: Node implements VisitorNode; declare parents: RegularNode implements VRegularNode; declare parents: LeafNode implements VLeafNode;}class MyVisitor implements VP.NodeVisitor { ... public void visitRegularNode(VP.VisitorNode node) { // do some operation on a regular node... } public void visitLeafNode(VP.VisitorNode node) { // do some operation on a leaf node... }}

DecoratorDecorator

• GoF: ''Attach additional responsibility to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality.''

– Add extra responsibility or functionality – Control decoration of individual objects

based on the context they are in

class ConcreteOutput { public void print(String s) { System.out.println(s); }}aspect StarDecorator dominates BracketDecorator {

/* identify the execution points of interest */ protected pointcut printCall(String s): call( void ConcreteOutput.print(String)) && args(s);

/* parameter s is the string to be decorated */ protected void around(String s): printCall(s) { s = '' *** '' + s + '' *** ''; proceed(s); }}

Observer Visitor Decorator

-

- -

-

-

Kinds of aspects

Concrete instanceextends reusableabstract aspect.

Concrete instanceextends reusableabstract aspect.

Decorator directlyimplemented bymeans of aspect.

Assignment of roles

Parent declarationfor subject(s) and

observers.

Parent declarationfor elementsto be visited.

Attached functionality

Introduction ofaccept methodsinto elements.

Event handling

Concretize anabstract pointcutto trigger events.

Pointcut in aspectidentifies executionpoints of interest.

Positive points

Use of existingclasses. Changedependencies.

Use of existingsubject classes.

Use of existingsubject classes.

Negative points

Only two classessupported by

pattern protocol.

No dynamiccomposition. Less reusable.

Bachelor Project ResultsBachelor Project Results

• Patterns with only superimposed roles benefit most from AspectJ, in contrast to patterns with only defining roles

• Although AspectJ improves modularity of many patterns, sometimes the AspectJ implementation has negative points

• AspectJ allows separating the mechanism and policy of some design patterns

Any Questions?Any Questions?

• This presentation as well as the bachelor project report with the analysis of pattern implementations in Java and AspectJ can be downloaded from the course website at http://www.cs.vu.nl/~ralf/poosd/