Title: AspectJ - Java based AOP System
1AspectJ - Java based AOP System
2AspectJ - basic features
- Compatible extension to Java
- Upward Compatibility - all legal Java programs
are legal AspectJ programs - Platform Compatibility - all legal AspectJ
programs run on all standard Java VM - Tool Compatibility - existing tools can be
extended to support AspectJ in a natural way
IDEs, documentation and design tools - Programmer Compatibility - Programming with
AspectJ must feel like a natural extension to
programming with Java
3AspectJ - basic features (contd.)
- AspectJ program structure
- Classes - like in Java
- Aspects - for concerns that crosscut class
structure - AspectJ crosscutting implementation
- Dynamic - define additional implementation to run
at certain point of program execution - Static - define new operation on existing types
(introduction)
4AspectJ - language overview
- Basic concepts
- Joinpoint - certain points in a programs
execution (for example - a call to a class
method - Pointcut - Program constructs to designate
joinpoints and to collect specific context at
these points - Advice - Code that runs upon meeting certain
conditions - Aspect - class like crosscutting unit, where
advice and pointcuts form weaving rules
5Joinpoints
- certain points in a programs execution
- have context associated with them (for example a
method call joinpoint can have the target object
as a part of the context - in AspectJ, available joinpoints are limited to
the following - Method call and execution
- Constructor call and execution
- Read/Write access to field
- Exception handler execution
- Object and class Initialization execution
6Pointcut designators
- Program constructs to designate Joinpoints
- set of Joinpoints and (optionally) some values
from their execution context - AspectJ provides primitive pointcut designators
which can be used to compose named/anonymous user
defined pointcuts
7Pointcut designators (contd.)
- primitive pointcut designators
- calls(signature) / receptions(signature) /
executions(signature) - matches
call/reception/execution join points at which the
method/constructor called matches signature
method signature ResultTypeName
RecvrTypeName.meth_id (params) constructor
signature NewObjectTypeName.new (params) - gets(signature) / gets(signature) val /
sets(signature) / sets(signature) oldVal /
sets(signature) oldVal newVal - matches get /
set join points where the field accessed matches
signature
field signature FieldTypeName
ObjectTypeName.field_id
8Pointcut designators (contd.)
- primitive pointcut designators (contd)
- handles(ThrowableType) - matches exception
handler execution join point of the specified
type - instanceof(CurrentlyExecutingObjectType) - this
is of specified type - within(ClassName) / withincode(signature) -the
executing code is contained within ClassName /
within the specified method - cflow(pointcut_designator) - for example ltcflow
(call ( MyClass.myMethod (..))gt - all joint
points in control flow of call to the method
9Pointcut designators (contd.)
- primitive pointcut designators (contd)
context collecting pointcuts - this(object) - all the join points where this
is the object specified - target(object) - the method is called on
specified object - args(arg1, ..) - the join points where the
arguments are as specified - named / unnamed pointcuts (like named / unnamed
classes) - use , , !, .., , to compose pointcuts
10Advices
- Associate code with a specific pointcut
- Advice types available before, after (after
returning / after throwing), around - the context is passed to advice by the pointcut
- example pointcut move (Line l)
receptions (void l.MoveXY (int, int)) after
(Line l) move (l) /print msg/
11Advices (contd.)
- Order of advice execution
- any around advise (most specific first) the
invocation of proceed () invokes next most
specific around advise - any before advice, most specific first
- the computation itself
- all after advice, less specific first
- return value from step (3) is returned to the
innermost call to proceed () and that piece of
around advice continues running - when the innermost around advice finishes, the
surrounding around advice continues running - once the outermost piece of around advice
returns, control continues back from the join
point
12Advices (contd.)
- Aspect precedence (for two pieces of advice a1,a2
defined in aspects A1,A2 respectively) - if A1 A2, the advice that appears first in the
aspects declaration body is more specific - A1 extends A2 --gt a1 is more specific
- declaration of A1 includes a dominates modifier
that mentions A2 --gt a1 is more specific than a2
13Aspects
- Modular units of crosscutting implementation
- declaration - similar to class declaration
- include pointcut declarations, advice
declarations and declarations permitted in class
declaration - aspect inheritance, abstract aspects are supported
14Example1 - thread pooling
- Thread pooling - more effective and resource
saving approach to thread managenment - AOP implementation in a modular fashion - source
code need not be modified - original code - simple multithreaded Server
15The server source code
// UppercaseServer.javaimport java.io.import
java.net.public class UppercaseServer
public static void main(String args) throws
Exception if (args.length ! 1)
System.out.println("Usage java
UppercaseServer ")
System.exit(1) int portNum
Integer.parseInt(args0) ServerSocket
serverSocket new ServerSocket(portNum)
while(true) Socket requestSocket
serverSocket.accept() Thread
serverThread new Thread(new UppercaseWorker(requ
estSocket)) serverThread.start()
16class UppercaseWorker implements Runnable
private Socket _requestSocket public
UppercaseWorker(Socket requestSocket) throws
IOException System.out.println("Creating
new worker") _requestSocket
requestSocket public void run()
BufferedReader requestReader null
Writer responseWriter null try
requestReader new BufferedReader(new
InputStreamReader(_requestSocket.getInputStr
eam())) responseWriter new
OutputStreamWriter(_requestSocket.getOutputStream(
))
17 while(true) String requestString
requestReader.readLine() if (requestString
null) break System.out.println("Got request
" requestString) responseWriter.write(requestS
tring.toUpperCase() "\n") responseWriter.flush
() catch(IOException ex)
finally try if (responseWriter !
null) responseWriter.close() if
(requestReader ! null) requestReader.close()
_requestSocket.close() catch
(IOException ex2) System.out.println("Ending
the session")
18// ThreadPool.java - simple class that acts
like stack for available threadsimport
java.util. public class ThreadPool List
_waitingThread new Vector() public void
put(DelegatingThread thread) System.out.printl
n("Putting back " thread) _waitingThread.add
(thread) public DelegatingThread get()
if (_waitingThread.size() ! 0)
DelegatingThread availableThread
(DelegatingThread)_waitingThread.remove(0)
System.out.println("Providi
ng for work " availableThread)
return availableThread
return null static class
DelegatingThread extends Thread private
Runnable _delegatee public void
setDelegatee(Runnable delegatee)
_delegatee delegatee public void
run() _delegatee.run()
19Adding thread pooling
// ThreadPooling.javapublic aspect ThreadPooling
ThreadPool pool new ThreadPool()
//
// Thread creation
//
pointcut
threadCreation(Runnable runnable)
call(Thread.new(Runnable)) args(runnable)
Thread around(Runnable runnable)
threadCreation(runnable)
ThreadPool.DelegatingThread availableThread
pool.get() If (availableThread null)
availableThread new ThreadPool.DelegatingThre
ad() availableThread.setDelegatee(r
unnable) return availableThread
20Adding thread pooling (contd.)
//
// Session
//
pointcut
session(ThreadPool.DelegatingThread thread)
execution(void ThreadPool.DelegatingThread.run())
this(thread)void around(ThreadPool.Delegatin
gThread thread) session(thread)
while(true) proceed(thread)
pool.put(thread) synchronized(thread)
try thread.wait()
catch(InterruptedException ex)
21Adding thread pooling (contd.)
//
// Thread start //
pointcut
threadStart(ThreadPool.DelegatingThread thread)
call(void Thread.start())
target(thread)void around(Thread thread)
threadStart(thread) if (thread.isAlive())
// wake it up synchronized(thread)
thread.notifyAll()
else proceed(thread)
22The implementation in details
- threadCreation() captures the creating a new
thread object taking a Runnable object as the
argument. - Advise the threadCreation() pointcut to first
check the thread pool for available threads. If
no thread is available, create a new one. Set the
delegatee to the Runnable object passed in and
return that object. No proceed() so the actual
operation is not executed - session() captures the run() method's execution
of any ThreadPool.DelegatingThread objects.
23The implementation in details (contd.)
- By putting session() inside a while(true) loop,
you advise session() to never finish the
servicing. That ensures a thread, once created,
never dies. Once a request is processed, you put
the thread back into thread pool and put the
thread into waiting state. - threadStart() captures a call to the
Thread.start() method. It uses isAlive() to check
if the thread previously started (thread obtained
from a pool and now in a waiting state) Wake up
the thread by notifying it. If the thread had not
started yet, proceed with starting the thread.
24Example 2 - Enforcement modularization
- Implement policy enforcement to ensure no
duplicate listener are added to the models, and
listeners do not loiter around when the view they
represent become usable. - Policy enforcement implementation in more useful
and easy way - no documentation,code reviews and
so on.
25Problems with listeners
- let you add a listener object more than once,
which leads to duplicate work if an
event-notification method carries an expensive
operation. - Easy to forget to remove listeners before
destroying a view - cause the listener to
consuming memory.
26aspect structural view
- need to implement 2 concerns
- uniqueness concern
- no loitering-views concern
27Base aspect EventListenerManagement
- This aspect contains an addListenerCall()
pointcut that captures calls to methods adding a
listener. - // EventListenerManagement.javaimport
java.util.public abstract aspect
EventListenerManagement pointcut
addListenerCall(Object model, EventListener
listener) call(void .addListener(EventListene
r)) target(model) args(listener)
modelAndListenerTypeMatch()abstract pointcut
modelAndListenerTypeMatch()
28Implement the uniqueness concern
- checks whether that listener was previously
added. If that listener is already present, the
operation does not proceed otherwise, it adds
the listener - advises the addListenerCall() pointcut to check
for the listener's uniqueness by looking in a
list obtained by invoking getCurrentListeners().
It proceeds with adding the listener only if the
list doesn't include a listener
29Implement the uniqueness concern - contd.
- // EventListenerUniqueness.javaimport
java.util.import javax.swing.import
javax.swing.event.import javax.swing.table.
public abstract aspect EventListenerUniqueness
extends EventListenerManagement void
around(Object model, EventListener listener)
addListenerCall(model, listener)
30Implement the uniqueness concern - contd.
- EventListener listeners getCurrentListeners(mo
del)if (!Utils.isInArray(listeners, listener))
System.out.println("Accepting "
listener)proceed(model, listener) else
System.out.println("Already listening "
listener)public abstract EventListener
getCurrentListeners(Object model)
31Implement the uniqueness concern - contd.
- the concrete aspect TableModelListenerUniqueness
extends EventListenerUniqueness to apply the
aspect to TableModel and related classes. It
provides an implementation for the
modelAndListenerTypeMatch() pointcut to restrict
the model type to AbstractTableModel and the
listener type to TableModelListener.
32Implement the uniqueness concern - contd.
- // TableModelListenerUniqueness.javaimport
java.util.EventListenerimport
javax.swing.event.TableModelListenerimport
javax.swing.table.aspect TableModelListenerUni
queness extends EventListenerUniqueness
pointcut modelAndListenerTypeMatch()
target(AbstractTableModel) args(TableModelListe
ner)public EventListener getCurrentListeners(
Object model) return ((AbstractTableModel)model)
.getListeners(TableModelListener.class)
33Implement a no loitering-views concern
- ensuring that no view loiters after its
destruction. - It advises addListenerCall() to proceed with the
listener obtained by calling the
getWeakListener() method.
34Implement a no loitering-views concern - contd.
- // EventListenerWeakening.javaimport
java.lang.ref.import java.util.import
javax.swing.event.public abstract aspect
EventListenerWeakening extends
EventListenerManagement dominates
EventListenerUniqueness void around(Object
model, EventListener listener)
addListenerCall(model, listener) proceed(model,
getWeakListener(listener))public abstract
EventListener getWeakListener(EventListener
listener)
35Implement a no loitering-views concern - contd.
- The TableModelListenerWeakening aspect handles
table-related listeners. It uses a specialized
WeakEventListener that implements
TableModelListener by delegating to the referent
object.
36Implement a no loitering-views concern - contd.
- // TableModelListenerWeakening.javaimport
java.util.import javax.swing.event.import
javax.swing.table.public aspect
TableModelListenerWeakening extends
EventListenerWeakening pointcut
modelAndListenerTypeMatch() target(AbstractTabl
eModel) args(TableModelListener)public
EventListener getWeakListener(EventListener
listener) System.out.println("Weakening "
listener)return new WeakTableModelListener((Tabl
eModelListener)listener)
37Implement a no loitering-views concern - contd.
- public class WeakTableModelListener extends
WeakEventListener implements TableModelListener
public WeakTableModelListener(TableModelListene
r delegatee) super(delegatee)public void
tableChanged(TableModelEvent e)
TableModelListener listener
(TableModelListener)getDelegatee()listener.table
Changed(e)
38Implement a no loitering-views concern - contd.
- static aspect TableRemoveGarbageCollectedListener
s extends WeakEventListener.RemoveGarbageCollecte
dListeners pointcut lexicalScopeMatch()
within(WeakTableModelListener)public void
removeListener(EventObject event, EventListener
listener) ((TableModel)event.getSource()).remov
eTableModelListener((TableModelListener)listener)
39Example 3 Characteristic-based implementation
modularization
- Operations with the same characteristics should
typically implement common behaviors. for example
you may need to authenticate access to all
security-critical data.
40Characteristic-based implementation modularization
- declare the aspect adding characteristic-based
crosscutting behavior as an abstract aspect. - declare an abstract pointcut for methods with
characteristics under consideration. - write an advice performing the required
implementation.
41SlowMethodAspect's implementation
- abstract slowMethods() pointcut and advises it to
first put a wait cursor, proceed with the
original operation, and finally restore the
original cursor.
42SlowMethodAspect's implementation - contd.
- // SlowMethodAspect.javaimport
java.util.import java.awt.import
java.awt.event.public abstract aspect
SlowMethodAspect abstract pointcut
slowMethods(Component uiComp)void
around(Component uiComp) slowMethods(uiComp)
Cursor originalCursor uiComp.getCursor()Curs
or waitCursor Cursor.getPredefinedCursor(Cursor.
WAIT_CURSOR)uiComp.setCursor(waitCursor)
43SlowMethodAspect's implementation - contd.
- try proceed(uiComp) finally
uiComp.setCursor(originalCursor)
44SlowMethodAspect's implementation - contd.
- Two test components, GUIComp1 and GUIComp2, nest
a concrete implementation of the aspect. - public static aspect SlowMethodsParticipant
extends SlowMethodAspect pointcut
slowMethods(Component uiComp) execution(void
GUIComp1.performOperation1()) this(uiComp)
45SlowMethodAspect's implementation - contd.
- public static aspect SlowMethodsParticipant
extends SlowMethodAspect pointcut
slowMethods(Component uiComp) (execution(void
GUIComp2.performOperation1()) execution(void
GUIComp2.performOperation2()))
this(uiComp)