1 / 45

AspectJ - Java based AOP System

AspectJ - Java based AOP System. AspectJ - 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

emmy
Download Presentation

AspectJ - Java based AOP System

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. AspectJ - Java based AOP System

  2. AspectJ - 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

  3. AspectJ - 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)

  4. AspectJ - language overview • Basic concepts: • Joinpoint - certain points in a program’s 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

  5. Joinpoints • certain points in a program’s 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

  6. Pointcut 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

  7. Pointcut 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

  8. Pointcut 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 <cflow (call (* MyClass.myMethod (..))> - all joint points in control flow of call to the method

  9. Pointcut 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

  10. Advices • 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*/}

  11. Advices (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

  12. Advices (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 aspect’s declaration body is more specific • A1 extends A2 --> a1 is more specific • declaration of A1 includes a dominates modifier that mentions A2 --> a1 is more specific than a2

  13. Aspects • 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

  14. Example1 - 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

  15. The 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(args[0]); ServerSocket serverSocket = new ServerSocket(portNum); while(true) { Socket requestSocket = serverSocket.accept(); Thread serverThread = new Thread(new UppercaseWorker(requestSocket)); serverThread.start(); } }}

  16. class 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.getInputStream())); responseWriter = new OutputStreamWriter(_requestSocket.getOutputStream());

  17. while(true) { String requestString = requestReader.readLine(); if (requestString == null) {break;} System.out.println("Got request: " + requestString); responseWriter.write(requestString.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.println("Putting back: " + thread); _waitingThread.add(thread); } public DelegatingThread get() { if (_waitingThread.size() != 0) { DelegatingThread availableThread =(DelegatingThread)_waitingThread.remove(0); System.out.println("Providing 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();} }}

  19. Adding 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.DelegatingThread(); } availableThread.setDelegatee(runnable); return availableThread; }

  20. Adding thread pooling (contd.) //=====================================================================// Session //=====================================================================pointcut session(ThreadPool.DelegatingThread thread): execution(void ThreadPool.DelegatingThread.run()) && this(thread);void around(ThreadPool.DelegatingThread thread) : session(thread) { while(true) { proceed(thread); pool.put(thread); synchronized(thread) { try { thread.wait(); } catch(InterruptedException ex) {} } }}

  21. Adding 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); }}}

  22. The 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.

  23. The 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.

  24. Example 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.

  25. Problems 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.

  26. aspect structural view • need to implement 2 concerns: • uniqueness concern • no loitering-views concern

  27. Base 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 *.add*Listener(EventListener+)) && target(model) && args(listener) && modelAndListenerTypeMatch();abstract pointcut modelAndListenerTypeMatch();}

  28. Implement 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:

  29. Implement 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) {

  30. Implement the uniqueness concern - contd. • EventListener[] listeners = getCurrentListeners(model);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);}

  31. Implement 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.

  32. Implement the uniqueness concern - contd. • // TableModelListenerUniqueness.javaimport java.util.EventListener;import javax.swing.event.TableModelListener;import javax.swing.table.*;aspect TableModelListenerUniqueness extends EventListenerUniqueness {pointcut modelAndListenerTypeMatch() : target(AbstractTableModel) && args(TableModelListener);public EventListener[] getCurrentListeners(Object model) {return ((AbstractTableModel)model).getListeners(TableModelListener.class); }}

  33. Implement 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.

  34. Implement 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);}

  35. Implement 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.

  36. Implement 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(AbstractTableModel) && args(TableModelListener);public EventListener getWeakListener(EventListener listener) {System.out.println("Weakening " + listener);return new WeakTableModelListener((TableModelListener)listener);}}

  37. Implement a no loitering-views concern - contd. • public class WeakTableModelListener extends WeakEventListener implements TableModelListener {public WeakTableModelListener(TableModelListener delegatee) {super(delegatee);}public void tableChanged(TableModelEvent e) {TableModelListener listener = (TableModelListener)getDelegatee();listener.tableChanged(e);}

  38. Implement a no loitering-views concern - contd. • static aspect TableRemoveGarbageCollectedListeners extends WeakEventListener.RemoveGarbageCollectedListeners {pointcut lexicalScopeMatch() : within(WeakTableModelListener);public void removeListener(EventObject event, EventListener listener) {((TableModel)event.getSource()).removeTableModelListener((TableModelListener)listener);}}}

  39. Example 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.

  40. Characteristic-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.

  41. SlowMethodAspect'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.

  42. SlowMethodAspect'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();Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);uiComp.setCursor(waitCursor);

  43. SlowMethodAspect's implementation - contd. • try {proceed(uiComp);} finally {uiComp.setCursor(originalCursor);}}}

  44. SlowMethodAspect'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);}

  45. SlowMethodAspect's implementation - contd. public static aspect SlowMethodsParticipant extends SlowMethodAspect {pointcut slowMethods(Component uiComp) : (execution(void GUIComp2.performOperation1())|| execution(void GUIComp2.performOperation2()))&& this(uiComp);}

More Related