CS 683 Emerging Technologies Spring Semester, 2003 AspectJ Syntax |
||
---|---|---|
© 2003, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 27-Jan-03 |
AspectJ Syntax
Point Example
public class Point { private double x; private double y; Point(double x, double y) { this.x = x; this.y = y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void setPolarCoordinates(double theta, double r) { x = r * Math.cos(theta); y = r * Math.sin(theta); } }
aspect PointChanged { private boolean Point.isDirty = false; public void Point.makeDirty() { isDirty = true; } public boolean Point.isDirty() { return isDirty; } public void Point.save() { isDirty = false; // add code to save point } pointcut fieldChanged(Point changed) : call( * Point.set*(..)) && target(changed); after(Point changed ) : fieldChanged(changed) { changed.makeDirty(); } }
import junit.framework.*; public class PointTests extends TestCase { public static void main( String args[]) { junit.swingui.TestRunner.run( PointTests.class); } public void testPointChange() { Point sample = new Point( 1, 1); assertFalse( sample.isDirty() ); sample.setX(5); assertTrue( sample.isDirty()); sample.save(); assertFalse( sample.isDirty() ); sample.setY(2); assertTrue( sample.isDirty()); sample.save(); assertFalse( sample.isDirty() ); } }
Why Not Just Use? public class Point { private double x; private double y; private boolean isDirty = false; Point(double x, double y) { this.x = x; this.y = y; } public void setX(double x){ this.x = x; isDirty = true; } public void setY(double y) { this.y = y; isDirty = true; } public void setPolarCoordinates(double theta, double r) { x = r * Math.cos(theta); y = r * Math.sin(theta); isDirty = true; } public boolean isDirty() { return isDirty; } public void save() { isDirty = false; // add code to save point } }
Possible Reasons to Use Aspects over Hand Coding
Aspect Terms
pointcut fieldChanged(Point changed) : call( * Point.set*(..)) && target(changed);
Aspect Terms
after(Point changed ) : fieldChanged(changed) { changed.makeDirty(); }
private boolean Point.isDirty = false;
Pointcut Designators
AspectJ Primitive Pointcuts
Simple Composing of Pointcuts
Operators that combine pointcuts
Wildcards in Pointcuts
execution(* *(..)) call(* set(..) execution(int *()) call(* setY(Double)) call(* Point.setY(int))
call(* Point.set*(int)) call( * Po*.set*(..)) call( * Po*.*et*(..))
When Advice can be Run
Before a pointcut
After a pointcut
Instead of a pointcut
Examples
Hello.java public class Hello { public static void main(String[] args ) { System.out.println("Hello"); } }
Before
public aspect HelloAspect { before() : call(void main(String[])) { System.out.println( "Advice"); } }
Output of running java Hello Advice
Hello
After
public aspect HelloAspect { after() : call(void main(String[])) { System.out.println( "Advice"); } }
Output from running java Hello Hello
Advice
Around
public aspect HelloAspect { void around() : call(void main(String[])) { System.out.println( "Advice"); } }
Output from running java Hello Advice
Some Forms of Before, after and around
before()
before(int k) : call( int * Point.*(int) ) && args(k)
before(Object k) : call( int * Point.*(Object) ) && args(k)
after () : call(int Foo.m(int))
after (int k) : call( int * Point.*(int) ) && args(k)
after () returning : call(int Foo.m(int))
after() returning(int x) : call(int Foo.m(int)) && args( x)
after() throwing : call(int Foo.m(int))
after() throwing (NotFoundException e) : call(int Foo.m(int))
returnType around(arguments) : pointcut
returnType around(arguments) throws ExceptionType : pointcut
Pointcut Primitives
Call
Call & Execution
Call
Simple Example
public class Hello { public static void main(String[] args ){ System.out.println("Hello"); } }
public aspect HelloAspect { before() : call(void main(String[])) { System.out.println( "call-before"); } after() : call(void main(String[])) { System.out.println( "call-after"); } before() : execution(void main(String[])) { System.out.println( "execution-before"); } after() : execution(void main(String[])) { System.out.println( "execution-after"); } }Output from running java Hello call-before
execution-before
Hello
execution-after
call-after
Why Execution?
A method/constructor can be run but not called
public class Hello { public Hello() { this(5); System.out.println("Hello()"); } public Hello(int x) { System.out.println("Hello(" + x + ")"); } public static void main(String[] args ) { new Hello(); } }
public aspect HelloAspect { before() : call( Hello.new(..) ) { System.out.println( "call-before"); } before() : execution(Hello.new(..)) { System.out.println( "execution-before"); } }Output from running java Hello call-before
execution-before
Hello(5)
execution-before
Hello()
Super and Call public class Hello { public void foo() { System.out.println( "Hello.foo"); } public static void main(String[] args ) { Hello test = new HelloChild(); test.foo(); } }
public class HelloChild extends Hello { public void foo() { super.foo(); System.out.println( "HelloChild.foo"); } }
public aspect HelloAspect { before() : call( * foo(..) ) { System.out.println( "call-before"); } before() : execution(* foo(..)) { System.out.println( "execution-before"); } }Output from running java Hello call-before
execution-before
execution-before
Hello.foo
HelloChild.foo
Reflection and Call
import java.lang.reflect.*; public class Hello { public void foo() { System.out.println( "Hello.foo"); } public static void main(String[] args ) throws Exception { Class helloClass = Hello.class; Class[] argumentTypes = { }; Method foo = helloClass.getMethod( "foo", argumentTypes ); Object[] arguments = { }; Hello test = new Hello(); foo.invoke( test, arguments ); } }
public aspect HelloAspect { before() : call( * foo(..) ) { System.out.println( "call-before"); } before() : execution(* foo(..)) { System.out.println( "execution-before"); } }Output from running java Hello call-before
execution-before
Hello.foo
Accessing Fields with Primitive Pointcuts
get( )
Pointcut for reading a field
get( int Point.x)
set( !private * Point.*)
withincode
withincode( methodOrConstrutor )
pointcut fieldChanged(Point changed) : set( private double Point.*) && target(changed) && withincode(* Point.*(..));
pointcut fieldChanged(Point changed) : set( private double Point.*) && target(changed) && !withincode( Point.new(..));
pointcut fieldChanged(Point changed) : set( private double Point.*) && target(changed) && withincode(* *.*(..));
Example Using set and withincode
Mark a Point object dirty if x or y changes outside of the constructor
aspect PointChanged { private boolean Point.isDirty = false; public void Point.makeDirty() { isDirty = true; } public boolean Point.isDirty() { return isDirty; } public void Point.save() { isDirty = false; // add code to save point } pointcut fieldChanged(Point changed) : set( private double Point.*) && target(changed) && !withincode( Point.new(..)); after(Point changed ) : fieldChanged(changed) { System.out.println("Make Dirty"); changed.makeDirty(); } }
Tests import junit.framework.*; public class PointTests extends TestCase { public static void main( String args[]) { junit.swingui.TestRunner.run( PointTests.class); } public void testPointChange() { Point sample = new Point( 1, 1); assertFalse( sample.isDirty() ); sample.setX(5); assertTrue( sample.isDirty()); sample.save(); assertFalse( sample.isDirty() ); sample.setY(2); assertTrue( sample.isDirty()); sample.save(); assertFalse( sample.isDirty() ); } }
Warning about Errors in the Example
Platform: Mac OS 10.2.3
Java: jdk 1.3.1 (build 1.3.1-root_1.3.1_020714-12:46)
AspectJ Browser
AspectJ 1.0.6
A bus error occurs when running the example with the definition:
pointcut fieldChanged(Point changed) : set( private * Point.*) && target(changed) && withincode(* *.*(..));That is using * for the type of the field in set
AspectJ Browser does not compile the example with the definition:
pointcut fieldChanged(Point changed) : set( * double Point.*) && target(changed) && withincode(* *.*(..));
That is * is used as the access level for the field in set
Copyright ©, All rights reserved.
2003 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 27-Jan-03    Next