Title: AOP Aspect Oriented Programming
1AOP Aspect Oriented Programming
- Advanced features
- using the AspectJ tool
By Ohad Barzilay, Computer Science Department,
Tel-Aviv University
2On the agenda
- Introducing more constructs of the AspectJ
language - Context collection mechanism
- Static and dynamic pointcuts
- AspectJ as role enforcement tool
- EJB
- Multiple interface
- Case study Implementing the observer design
pattern
3a simple figure editor
Display
2
4Introducing more constructs of the AspectJ
language
- Context collection mechanism
- Static and dynamic pointcuts
5More constructs of AspectJ
- Context exposures
- this()
- target()
- args()
- Also used as predicates on join points
6Explaining parameters
- value is pulled
- right to left across left side
right side - from pointcuts to user-defined pointcuts
- from pointcuts to advice, and then advice body
pointcut move(Line l) target(l)
(call(void Line.setP1(Point)) call(void
Line.setP2(Point))) after(Line line)
move(line) ltline is bound to the linegt
7A polymorphic pointcut
- target(ltsupertype namegt)
- does not further restrict the join points
- does pick up the target object
pointcut move(FigureElement figElt)
target(figElt) (call(void
Line.setP1(Point)) call(void
Line.setP2(Point)) call(void
Point.setX(int)) call(void
Point.setY(int))) after(FigureElement fe)
move(fe) ltfe is bound to the figure
elementgt
8Other primitive pointcuts
- this(lttype namegt)
- currently executing object is an instance of type
or class name - within(lttype namegt)
- currently executing code is contained within
class name - withincode(ltmethod/constructor signaturegt)
- currently executing code is specified method or
constructor - get(int Point.x)
- set(int Point.x)
- field reference or assignment join points
9this vs. within
- this(lttype_name or idgt)
- Type matching
- Including subclasses
- Enables context collection
- within(lttype patterngt)
- Lexical scope matching
- Including inner classes and Static methods
- Test yourself
- How can I match all the join points of subclasses
of the class Base ? - What is the difference between call(
Account.(..)) and call( .(..))
this(Account)
10this vs. within Answers
- this(Base) !within(Base)
-
- call( Account.(..)) matches all instance and
static methods defined in Acount - call( .(..)) this(Account) matches the same
instance methods and any methods in the
subclasses of Account, but none of static methods
11Fine-grained protection
a runtime error
class Figure public Point makeLine(Line p1,
Line p2) new Line... public Point
makePoint(int x, int y) new Point...
... aspect FactoryEnforcement pointcut
illegalNewFigElt() (call(Point.new(..))
call(Line.new(..))) !withincode(
Figure.make(..)) before()
illegalNewFigElt() throw new Error("Use
factory method instead.")
want to ensure that any creation of figure
elements goes through the factory methods
12Fine-grained protection
a compile-time error
class Figure public Point makeLine(Line p1,
Line p2) new Line... public Point
makePoint(int x, int y) new Point...
... aspect FactoryEnforcement pointcut
illegalNewFigElt() (call(Point.new(..))
call(Line.new(..))) !withincode(
Figure.make(..)) declare error
illegalNewFigElt() "Use factory method
instead."
want to ensure that any creation of figure
elements goes through the factory methods
must be a static pointcut(more on this later)
13Fine-grained protection
a compile-time error polymorphism
class Figure public Point makeLine(Line p1,
Line p2) new Line... public Point
makePoint(int x, int y) new Point...
... aspect FactoryEnforcement pointcut
illegalNewFigElt() call(FigureElement.new(..
)) !withincode( Figure.make(..))
declare error illegalNewFigElt() "Use
factory method instead."
want to ensure that any creation of figure
elements goes through the factory methods
must be a static pointcut(more on this later)
14Fine-grained protection
as a static inner aspect
class Line implements FigureElement private
Point p1, p2 Point getP1() return p1
Point getP2() return p2 void setP1(Point
p1) this.p1 p1 void setP2(Point p2)
this.p2 p2 void moveBy(int dx, int dy)
... static aspect SetterEnforcement
declare error set(Point Line.)
!withincode(void Line.setP(Point))
"Use setter method, even inside Line class."
15call vs. execution
Class A ... SomeProc(B b) ... b.f()
Class B ... f() ...
16call vs. execution (2)
- within and withincode match differently
- call(void m()) withincode(void m()) matches
only directly recursive calls - execution(void m()) withincode(void m()) is
the same as execution(void m()) - The call join point does not capture super calls
to non-static methods
17call vs. execution (3)
- Rule of thumb
- If you want to pick a join point that runs when
an actual piece of code runs (as in tracing), use
execution - If you want to pick one that runs when a
particular signature is called (as in production
aspects), use call
18Control flow pointcuts
- cflow(pointcut)
- cflowbelow(pointcut)
- With respect to the call stack
- Select non-recursive calls
- pointcut TopLevelFactorial()
- call ( factorial(..))
- !cflowbelow(call ( factorial(..)))
19Counting bytes
interface OutputStream public void
write(byte b) public void write(byte
b) / This SIMPLE aspect keeps a global
count of all the bytes ever written to an
OutputStream. / aspect ByteCounting int
count 0 int getCount() return count
// // // what goes here?
// // //
20Counting bytes
/ This SIMPLE aspect keeps a global count of
all all the bytes ever written to an
OutputStream. / aspect ByteCounting int
count 0 int getCount() return count
complete the codefor ByteCounting
21Counting bytes v1
aspect ByteCounting int count 0 int
getCount() return count after()
returning call(void
OutputStream.write(byte)) count count 1
after(byte bytes) returning
call(void OutputStream.write(bytes)) count
count bytes.length
First attempt
22counting bytes
some stream implementations
class SimpleOutputStream implements OutputStream
public void write(byte b)
public void write(byte b) for (int i 0 i
lt b.length i) write(bi) class
OneOutputStream implements OutputStream
public void write(byte b) public
void write(byte b)
23counting bytes
another implementation
class OtherOutputStream implements OutputStream
public void write(byte b) byte bs
new byte1 b write(bs)
public void write(byte b)
24counting bytes v2
using cflowbelow for more robust counting
aspect ByteCounting int count 0 int
getCount() return count pointcut
write() call(void OutputStream.write(byte))
call(void OutputStream.write(b
yte)) pointcut writeCflow()
cflowbelow(write()) after() returning
!writeCflow() call(void OutputStream
.write(byte)) count after(byte
bytes) returning !writeCflow() call(void
OutputStream .write(bytes)) count count
bytes.length
25More Constructs
- Inter-type member declarations
- Modifiers Type OnType . Id(Formals)
ThrowsClause Body - abstract Modifiers Type OnType . Id(Formals)
ThrowsClause -
- Extension and Implementation
- declare parents TypePattern extends Type
- declare parents TypePattern implements TypeList
- Exception handler execution-related pointcuts
- handler(TypePattern)
- Warnings and Errors
- declare error Pointcut String
- declare warning Pointcut String
26More Constructs (2)
- Softened exceptions
- declare soft Type Pointcut
- Advice Precedence
- declare precedence TypePatternList
- Advice execution-related pointcuts
- adviceexecution()
- Expression-based pointcuts
- if(BooleanExpression)
27AspectJ as role enforcement tool
- The bean problem
- Interface implementation
- Observer design pattern
28The Bean Aspect
- Java beans are reusable software components that
can be visually manipulated in a builder tool.
29The Bean Aspect (2)
- The requirements for an object to be a bean are
few - Beans must define a no-argument constructor
- Must be either Serializable or Externalizable.
- Must publish the methods getproperty and set
property where property is the name of a field in
the bean class. - Bound properties should fire events whenever
their values change so that any registered
listeners (such as, other beans) will be informed
of those changes. - Making a bound property involves keeping a list
of registered listeners, and creating and
dispatching event objects in methods that change
the property values, such as setproperty methods.
30The Bean Aspect (3)
- Point is a simple class representing points with
rectangular coordinates. - Point does not know anything about being a bean
there are set methods for x and y but they do not
fire events, and the class is not serializable.
31Roles/Views
32CloneablePoint
- aspect CloneablePoint
- declare parents Point implements Cloneable
- public Object Point.clone() throws
- CloneNotSupportedException
-
- // we choose to bring all fields
- // up to date before cloning
- makeRectangular() // defined in class
Point - makePolar() // defined in class
Point - return super.clone()
-
-
33Case study
- Implementing the observer design pattern
34The problem
- Define a one to many dependency between objects
- Also known as publish-subscribe
- In java swing and in Smalltalk, known as MVC
(Model/View/Controller)
35The Solution
36The Implementation
- Pattern introduces code in all potential
participants - Changes to protocol etc. require far-reaching
refactoring - Pattern disappears into the code
- Pattern code not reusable
37Abstract and Concrete Aspects
- The parts common to all instantiations are
- The existence of Subject and Observer roles (i.e.
the fact that some classes act as Observer and
some as Subject). - Maintenance of a mapping from Subjects to
Observers. - The general update logic Subject changes trigger
Observer updates. - The parts specific to each instantiation of the
pattern are - Which classes can be Subjects and which can be
Observers. - A set of changes of interest on the Subjects that
trigger updates on the Observers - The specific means of updating each kind of
Observer when the update logic requires it.
38Abstract and Concrete Aspects
39Abstract Observer Protocol aspect
public abstract aspect ObserverProtocol
protected interface Subject protected
interface Observer abstract protected
pointcut subjectChange(Subject s) abstract
protected void updateObserver(Subject s, Observer
o) private WeakHashMap perSubjectObservers
protected List getObservers(Subject s) if
(perSubjectObservers null)
perSubjectObservers new WeakHashMap()
List observers (List)perSubjectObservers.get(s)
if ( observers null ) observers
new LinkedList() perSubjectObservers.put(s,
observers) return observers
public void addObserver(Subject s,Observer o)
getObservers(s).add(o) public void
removeObserver(Subject s,Observer o)
getObservers(s).remove(o) after(Subject s)
subjectChange(s) Iterator iter
getObservers(s).iterator() while (
iter.hasNext() ) updateObserver(s,
((Observer)iter.next()))
Roles
Conceptual OPs
Observer update
Mapping
Update logic
40Abstract Observer Protocol aspect
public abstract aspect ObserverProtocol
protected interface Subject protected
interface Observer abstract protected
pointcut subjectChange(Subject s) abstract
protected void updateObserver(Subject s,
Observer o) after(Subject s)
subjectChange(s) Iterator iter
getObservers(s).iterator() while (
iter.hasNext() ) updateObserver(s,((Obse
rver)iter.next())) ...
Roles
Conceptual OPs
Observer update
Update logic
41Abstract Observer Protocol aspect
public abstract aspect ObserverProtocol ...
private WeakHashMap perSubjectObservers
protected List getObservers(Subject s) if
(perSubjectObservers null) perSubjectObserver
s new WeakHashMap() List observers
(List)perSubjectObservers.get(s) if (
observers null ) observers new
LinkedList() perSubjectObservers.put(s,
observers) return observers
public void addObserver(Subject s,Observer o)
getObservers(s).add(o) public void
removeObserver(Subject s,Observer o)
getObservers(s).remove(o) ...
Mapping
42An Observer instance
public aspect CoordinateObserver extends
ObserverProtocol
declare parents Point implements Subject
declare parents Line implements Subject
declare parents Screen implements Observer
Assigned roles
protected pointcut subjectChange(Subject s)
(call(void Point.setX(int)) call(void
Point.setY(int)) call(void
Line.setP1(Point)) call(void
Line.setP2(Point))) target(s)
Conceptual OPs
protected void updateObserver(Subject s,
Observer o)
((Screen)o).display("Coordinate change.")
Observer update
43We achieved -
- Better code in sense of
- Locality
- Reusability
- Composition transparency
- (Un)pluggability
44A Discussion
- Doesnt multiple inheritance solve the view/role
aspect problem? - When it doesnt?
- When does multiple aspects backdoor the multiple
inheritance faults?
45More interesting examples
- Monitoring techniques logging, tracing and
profiling - Policy enforcement system wide contracts
- Optimization pooling (database connections,
threads) and caching - Authentication and authorization
- Transaction management
- Implementing thread safety
- Design patterns and idioms Â
46Classification of Aspects
- Development aspects
- Production aspects
- Policy enforcement
- Development or Production ?
47More AOP and AspectJ
- Online Documentation
- http//dev.eclipse.org/viewcvs/indextech.cgi/chec
kout/aspectj-home/doc/index.html - Mailing list
- http//aosd.net/
- Resources used in this presentation can be found
on my homepage - http//www.cs.tau.ac.il/ohadbr/aop
48More design patterns
- The Design Patterns Java Companion
- James W. Cooper
- http//www.patterndepot.com/put/8/JavaPatterns.ht
m - Thinking in Patterns with Java
- Bruce Eckel
- http//www.mindview.net/Books/TIPatterns/
- Design Pattern Implementation in Java and AspectJ
- Jan Hannemann and Gregor Kiczales
- http//www.cs.ubc.ca/jan/papers/oopsla2002/oopsl
a2002.html - Design Patterns - Elements of Reusable
Object-Oriented Software - by Erich Gamma, Richard Helm, Ralph Johnson,
John Vlissides (no online version)
49Questions ?