View
216
Download
0
Embed Size (px)
Citation preview
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); }