aspect orientated programming © university of liverpoolcomp 319slide 1

46
ASPECT ORIENTATED PROGRAMMING © University of Liverpool COMP 319 slide 1

Post on 19-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

ASPECT ORIENTATEDPROGRAMMING

© University of LiverpoolCOMP 319 slide 1

The problem• Code scattering

class BankAccount { public void transfer(int amount,BankAccount

toAccount) {try { Log.transferringMoney(); if (authenticated(username,password) {

// do transfer } } catch (TransactionException texc) { Log.storeExc(texc);}

© University of LiverpoolCOMP319 slide 2

Concerns and Cross cut concerns• Concern examples, banking- Transfer between accounts- Product statement-Make billing payment

• Cross cut concerns- Security/authentication- Logging- Transaction handling

© University of LiverpoolCOMP319 slide 3

Cross cut concern problems

• Scattering• Duplication- Code cloning

• Tangling- Concerns not properly separated

© University of LiverpoolCOMP319 slide 4

Cross cutting concern examples and approaches• Persistence-Object-relational mapping

• Internationalization- Resource bundling

• Code mobility- Pre-processing

• Error handling- Chained exceptions, error return codes

© University of LiverpoolCOMP319 slide 5

Definitions• 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

© University of LiverpoolCOMP319 slide 6

Terminology

• 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)

© University of LiverpoolCOMP319 slide 7

AOP Platforms

• AspectJ• Spring• JBoss AOP• AspectWerkz-Now working with AspectJ

• Java Aspect Components (JAC)

© University of LiverpoolCOMP319 slide 8

AspectJ

• Now an Eclipse project (http://eclipse.org/aspectj/)- Developed at Xerox PARC- Released 2001

• Latest version (AspectJ 5) is a collaboration of AspectJ and AspectWerkz

• AJDT - AspectJ Development Tools plug-in for Eclipse

© University of LiverpoolCOMP319 slide 9

Aspect definition

© University of LiverpoolCOMP319 slide 10

package com.aspect;

public aspect DemoAspect {

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

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

}

}

Point-cut

Advice

Aspect

Aspect example (Hello World)public class Main {

public static void main(String[] args) {// TODO Auto-generated method

stubhello();

}public static void hello() {

System.out.println("Hello");}

}

© University of LiverpoolCOMP319 slide 11

Aspect Example HelloWorld

public aspect Hello { pointcut helloCall() : execution( * Main.hello(..));

after() : helloCall() { System.out.println("World!!!"); }

}

© University of LiverpoolCOMP319 slide 12

Point cut definitions

© University of LiverpoolCOMP319 slide 13

//call is the most common joinpoint typecall([access modifier] returnType package.ClassName.method(args));

//Examplescall(* *.*(..)); //Note: “..” is also a wildcardcall(public * *.set*(..));call(void *.set*(..));call(* *.set*(int));call(String com.foo.Customer.set*(..));call(* com.foo.Customer+.set*(..)); //”+” cross-cuts childrencall(public void com..*.set*(int));call(* *.set*(int, ..));call(* *.set*(int, .., String));

Defining a pointcut

• pointcut nameOfPointCut() : definition;

• pointcut setters() :call(public * *.set*(..));

© University of LiverpoolCOMP319 slide 14

Types of Join point

• 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

© University of LiverpoolCOMP319 slide 15

Join points

public static void main(String argsv[]) { hello(); call}Public static void hello() { execution try { } catch (Exception e) { handler }}

© University of LiverpoolCOMP319 slide 16

Types of Join points• get(field expr)-when a field is read

• set(field expr)-when a field is set- pointcut settingLength() : set( int SetterMonitorExample.length);

• staticinitialization(class expr)-when a static block of a class is executed

© University of LiverpoolCOMP319 slide 17

Types of Join points

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

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

• adviceexecution()-when an advice block is executed

© University of LiverpoolCOMP319 slide 18

Adding Advice

© University of LiverpoolCOMP319 slide 19

pointcut everyCall() :

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

before() : everyCall(){

System.out.println(“Advice called before method");

}

after() : somePointCut(){

System.out.println("Advice called after each method");

}

Anonymous point cuts in Advice

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

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

}

// point cut doesn’t have name

© University of LiverpoolCOMP319 slide 20

Types of Advice• before()-Before call or body

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

© University of LiverpoolCOMP319 slide 21

Types of Advice

• after() returning [(type expr)]- called after normal execution of the joinpoint

• after() throwing [(exception expr)]- called if the execution of the joinpoint throws the specified exception

• after() - executes regardless (sort of like finally)

© University of LiverpoolCOMP319 slide 22

Types of Advice

• type around() [throws exception]-executes in place of a joint point of execution-You can stop or replace code execution-To call the original code, use proceed()

© University of LiverpoolCOMP319 slide 23

Types of Advice

• withincode(method expr)- true if joinpoint is within defined method

• within(type expr)- true if joinpoint is within defined type (i.e. class definition)

© University of LiverpoolCOMP319 slide 24

Exception handling in Advice

• after() throwing- Intercepts at method level, before the

catch() block• handler(exception type)- Intercepts at the catch() block

• declare soft : exception type- Wraps any exception as a

RuntimeException (which consequently no longer needs to be declared in the throws clause of the method)

© University of LiverpoolCOMP319 slide 25

Exception handling advice

before(java.io.FileNotFoundException exc) : handler(java.io.FileNotFoundException ) && args(exc) {System.out.println("Could not find file... message is "+exc.getMessage());}

© University of LiverpoolCOMP319 slide 26

Point cut operators

• if(expr)- evaluate boolean expression

• withincode(method expr)- true if joinpoint is within defined method

• within(type expr)- true if joinpoint is within defined type

© University of LiverpoolCOMP319 slide 27

Point cut operators

• this(type expr)- true when joinpoint matches source object

• target(type expr)- true when joinpoint matches target object

• args(type expr)- true for any joinpoint matching argument type list

© University of LiverpoolCOMP319 slide 28

Getting at the context

• Sometimes we want to get at- The instance of this, which is being used at the point of call- The target instance- Example fred.getX(); // fred is the

target- The arguments (x and y)- Example fred.setPosition(x,y)

© University of LiverpoolCOMP319 slide 29

Getting the context• Declaring the context, type- before(BankAccount account) :

• Declares the context type in the point cut, for example..

before(BankAccount account) : target(account) && authenticationNeeded() && (!execution(* BankAccount.authenticate(..))) {

account.authenticate(); }

-Question … Why do we have !execute(* BankAccount(authenticate())

© University of LiverpoolCOMP319 slide 30

Arguments example

pointcut settingLength(int length) : set( int SetterMonitorExample.length) && args(length);

void around(int inputLength) : settingLength1(inputLength) {

System.out.println("Trying to set length to "+inputLength);

if (inputLength<5) { proceed(inputLength); } else { System.out.println("Skipping length setting

length too large"); } }

© University of LiverpoolCOMP319 slide 31

Point cut logical operators

• &&- Logical AND

• ||- Logical OR

• !- Logical NOT

© University of LiverpoolCOMP319 slide 32

thisJoinPointthisJoinPoint.toString() thisJoinPoint.getKind() // call, execution, set, getthisJoinPoint.getSignature();

System.out.println("thisJoinPoint.getSourceLocation(): " + thisJoinPoint.getSourceLocation(); // source code line numberthisJoinPoint.getTarget(); // target objectthisJoinPoint.getThis(); // source object

© University of LiverpoolCOMP319 slide 33

thisJointPoint example

package testaspect;

public class AspectReflectionExample {public void greet() { Greeter greeter=new Greeter("Seb"); greeter.greet("Hello ");}public static void main(String argvs[]) { AspectReflectionExample instance=new AspectReflectionExample();instance.greet();

}

}

© University of LiverpoolCOMP319 slide 34

thisJointPoint example

© University of LiverpoolCOMP319 slide 35

package testaspect;

public class Greeter {private String name="";public void goodMorning() { System.out.println("Good morning "+name);}public void greet(String message) { System.out.println(message+name);}public Greeter(String name) { this.name=name;}}

thisJoinPoint example

© University of LiverpoolCOMP319 slide 36

package testaspect;

public aspect ReflectAspect {pointcut greetings(Greeter example) : call(* *.Greeter.greet(..)) && target(example);

before(Greeter example) : greetings(example) {System.out.println("this: " + this);System.out.println("thisJoinPoint.toString(): " + thisJoinPoint.toString() );System.out.println("thisJoinPoint.getKind(): " + thisJoinPoint.getKind() );System.out.println("thisJoinPoint.toLongString(): " + thisJoinPoint.toLongString() );System.out.println("thisJoinPoint.toShortString(): " + thisJoinPoint.toShortString() );System.out.println("thisJoinPoint.getClass(): " + thisJoinPoint.getClass() );System.out.println("thisJoinPoint.getSignature(): " + thisJoinPoint.getSignature() );System.out.println("thisJoinPoint.getSourceLocation(): " +thisJoinPoint.getSourceLocation() );System.out.println("thisJoinPoint.getTarget(): " + thisJoinPoint.getTarget() );System.out.println("thisJoinPoint.getThis(): " + thisJoinPoint.getThis() );

}

}

thisJoinpointthis: [email protected](): call(void testaspect.Greeter.greet(String))thisJoinPoint.getKind(): method-callthisJoinPoint.toLongString(): call(public void testaspect.Greeter.greet(java.lang.String))thisJoinPoint.toShortString(): call(Greeter.greet(..))thisJoinPoint.getClass(): class org.aspectj.runtime.reflect.JoinPointImplthisJoinPoint.getSignature(): void testaspect.Greeter.greet(String)thisJoinPoint.getSourceLocation(): AspectReflectionExample.java:6thisJoinPoint.getTarget(): [email protected](): testaspect.AspectReflectionExample@2afa3ac1

© University of LiverpoolCOMP319 slide 37

Modifying target classes• Inter type declarations- Aspect can add methods, field and constructors to external class

© University of LiverpoolCOMP319 slide 38

aspect SecurityChecksboolean BankAccount.authenticated=false;public void BankAccount.authenticate() {

if (authenticated) return; // TO DO more authentication code } public BankAccount.new(String password,String name, String pin) { }}

Modifying target classes

• You can also use inter-type declarations to change the inheritance, to add new interface or new super class

• New parent must be sub-class of existing parent

© University of LiverpoolCOMP319 slide 39

public aspect ChangeStructure {

declare parents: BankAccount implements Serializable; declare parents: BankAccount extends SecureObject;

}

Intertype declarations, compile control• declare parent• declare warning- Compiler warnings result from joinpoints

• declare error- Compiler errors result from joinpoints

• declare precedence-Define aspect precedence

© University of LiverpoolCOMP319 slide 40

Encouraging logging, using warnings

© University of LiverpoolCOMP319 slide 41

• Simple example- From Matt Chapman, AJDT Committer

public aspect EnforceLogging{

pointcut scope(): within(*);

pointcut printing():

get(* System.out) ||

get(* System.err) ||

call(* Throwable+.printStackTrace());

declare warning : scope() && printing(): "don't print, use the logger";

}

Class watcher example• Monitors all calls to setters• If data changes- Dirty flag=true

• Application can use this to- Save data only if dirty flag=true, saves

unrequired writes- Data can be discarded from cache if

dirty flag=false- Supports lazy writing caches- Help data integraty testing

© University of LiverpoolCOMP319 slide 42

Watcher Examplepublic aspect WatchSetters { // just to invoke test code below public static void main(String[] args) { Client.handleTimer(new Timer()); } private static final Class[] GETTER_ARG_TYPES = new Class[]{}; private static final Object[] GETTER_ARGS = new Object[]{}; private static final Object NONE = new Object(); public interface IWatched {} /** true if new value sent to any setter */ private boolean IWatched.dirty; /** false if unable to maintain dirty b/c no privileges, no getter... */ private boolean IWatched.dirtyValid = true; /** clients can use dirty flag */ public boolean IWatched.isDirty() { return dirty; } /** clients handle case when dirty flag is invalid */ public boolean IWatched.isDirtyValid() { return dirtyValid; }

© University of LiverpoolCOMP319 slide 43

Watcher example (Pointcut)

• public pointcut setters(IWatched watched) : target(watched) && execution(void IWatched+.set*(*)); // advice uses args[0]

© University of LiverpoolCOMP319 slide 44

Watch timer advice

© University of LiverpoolCOMP319 slide 45

void around(IWatched watched) : setters(watched) && if (watched.dirtyValid) { // get value by invoking getter method Object value = NONE; // no valueString getterName=“”;try { getterName = "g" + thisJoinPoint.getSignature().getName().substring(1); Method method = watched.getClass() .getMethod(getterName, GETTER_ARG_TYPES); value = method.invoke(watched, GETTER_ARGS); } catch (Throwable t) { } ; if (NONE == value) { watched.dirtyValid = false; proceed(watched); return; } // compare value with arg being set - pointcut has exactly 1 parm Object arg = thisJoinPoint.getArgs()[0]; if (!(null == arg ? value == null : arg.equals(value))) { proceed(watched); watched.dirty = true; } }

Watcher Example Persistence

© University of LiverpoolCOMP319 slide 46

if (!(null == arg ? value == null : arg.equals(value))) { proceed(watched); watched.dirty = true; String tableName=thisJoinPoint.getTarget().getClass().getName(); tableName=tableName.replace(".", "_"); String sql="update "+tableName+" set "+getterName.substring(3)+"='"+arg.toString()+"' where id='"+watched.id+"'"; System.out.println("sql : "+sql); }