Section 12.2. AOP USING REFLECTION


12.2. AOP USING REFLECTION

In this section, we show how to support AOP using reflection. We provide an example of this support based on a real-world application with multiple aspects. Aspects definitions and weaving are illustrated using MetaclassTalk and its MOP.

12.2.1. From Reflection to AOP

To show the relationships between reflection and AOP, we present a mapping from the concepts of AOP to those of reflection. This mapping illustrates how reflection can be used to separate aspect code and base code and to weave them together.

Aspect code is separated from base code thanks to the natural separation between the base-level and the meta-level. Base code is defined at the base-level, while aspects are defined at the meta-level. Base objects represent base code, and meta-objects represent aspects. Separating aspect definitions one from another is done by making use of a specific set of meta-objects for each aspect. Thus, each meta-object participates in a single aspect.

Weaving is performed using the meta-link and meta-object cooperation. Aspects are woven with base code using the meta-link. Indeed, the meta-link connects meta-objects, representing aspects, to base objects, representing base code. Usually, when weaving multiple aspects with base code, a given base object requires linking to multiple meta-objects. Conflicts arise when two meta-objects compete to control the same execution mechanism (e.g., the same message reception) of the same base object. Such conflicts can be solved by making meta-objects cooperate (whenever possible), as presented in Section 12.1.3.

One important notion related to weaving is the concept of join points. Join points correspond to particular points in the base code execution flow. The MOP provided by a reflective language defines and gives access to these points. For example, the MOP can state that meta-objects are active on message receptions. However, this definition is generic because it is not bound to base-code: It does not refer to a particular set of message receptions. The exact set of message receptions controlled by a given meta-object mo remains undefined until mo is linked to some base object o. Once this linkage is performed, the mo meta-object controls all messages received by o. So, reflection looses the coupling between aspect definitions and base-code, paving the way for aspect reuse.

To conclude, we draw an analogy between a reflective programming language and AspectJ [25, 26, 28]. Methods of meta-object classes play the role of sets of advice. The MOP can be viewed as a set of abstract pointcuts. Concreteness is obtained by linking a given base object to some meta-object since the meta-object acts on some concrete execution flow (i.e., some concrete join points such as a particular message send or field access).

12.2.2. Example of an Application with Multiple Aspects

Consider the example of a digital bookstore that sells books on the web (Figure 12-5). Among objects comprising the digital bookstore, we have customers, managers, books, and orders. The digital bookstore supports various functionalities such as searching for books, ordering books, adding and removing books, and updating price lists.

Figure 12-5. A digital bookstore.


The digital bookstore system also has several aspects with which developers should be concerned. Obviously, distribution is one of them. The digital library system should interact with remote entities (e.g., customers, bank). Another aspect is concurrency. Multiple customers can search for books or make orders while library managers handle orders or update the price list. Yet another aspect is persistence. It is crucial to make objects such as orders or books persist, even if the application stops running.

12.2.3. Separating Aspects

Thanks to the base-meta separation provided by reflection, we can decompose our digital bookstore application, as shown on Figure 12-6. On one hand, aspects are defined at the meta-level using meta-objects. On the other hand, application core functionalities are defined at the base-level using base objects.

Figure 12-6. Separating aspects in the bookstore application.


Separating aspects from each other is done by decomposing the meta-level into sets of meta-objects. Each set includes meta-objects specific to a single aspect.

The set of meta-objects specific to the distribution aspect includes meta-objects that make some base objects be remotely accessible or behave as proxies (possibly with cache). Meta-objects for a proxy forward all received messages to some remote-objects and take care of marshaling. Meta-objects for remote-objects register these in some name server and take care of marshaling.

The synchronization aspect is represented by a set of meta-objects that allow defining critical sections of code (e.g., mutually exclusive methods). For example, such a meta-object handles accesses to the price field of a book so that:

  • When the price is changed by some thread, other threads attempting either a read or a write access of the same field are locked.

  • When the price is read by some thread, other threads attempting a write access to the price field are locked.

The persistence aspect is represented by a set of meta-objects that define how base objects should be stored and when the storage should be updated. For example, a meta-object could handle accesses to book fields in order to update a database on changes.

Besides a set of meta-objects, an aspect definition in MetaclassTalk includes a configuration script. This latter is a code that

  • Creates meta-objects

  • Performs any required initialization for meta-objects (e.g., linking persistence meta-objects to some database)

  • Sets up the meta-link, that is, links the aspect's specific meta-objects to application base objects

For example, Figure 12-7 provides the code defining the synchronization aspect. This definition is quite simple. There is only one meta-object class named SynchronizationMetaObject, and the configuration script only ensures the creation of a synchronization meta-object for every instance of classes Book and Order. So, an instance of the SynchronizationMetaObject is created and linked to every new instance of one of these two classes.

Figure 12-7. Definition of a synchronization aspect.


The SynchronizationMetaObject class defines a new field named lock. This field holds a lock object that prevents critical sections of code from being executed by more than one thread simultaneously. We ensure this synchronization by making the SynchronizationMetaObject class redefine methods for controlling fields reads and writes. In each of those two methods (atIV:of: and atIV:of:put:), the critical section of code is between square brackets.

As stated previously, an aspect definition distinguishes between:

  • Aspect-specific processing provided by meta-object classes

  • When and where to perform this processing (i.e., join points) provided by the configuration script

Since the specification of join points is provided by the configuration script, meta-object classes are generic. Thus, they can be reused in different applications, paving the way for aspect reuse.

12.2.4. Weaving Aspects

In the context sketched in Section 12.2.3, weaving consists of performing configuration scripts of all aspects. As a result, each new base object involved in multiple aspects is linked to multiple meta-objects. These meta-objects cooperate in order to control the activity of the newly created base object. This cooperation can rely on the chain of responsibility design pattern described in Section 12.1.3.

For example, consider a book base object in our digital bookstore. It should be both synchronized and persistent. Each of these two concerns is represented by a specific meta-object. The synchronization meta-object ensures that only one thread can access (read or write) some field of a book. The persistence meta-object ensures that whenever a field value is changed (i.e., write access), the new value is stored on some database. We organize these two meta-objects in a chain, as shown in Figure 12-8. The synchronization meta-object is the head of the cooperation chain, and thus it is linked to the book object.

Figure 12-8. Weaving aspects using meta-objects cooperation.


In order to show the meta-object cooperation in action, let's examine what happens when the bookstore manager tries to update the price of some book. The price update means assigning a new value to the price field of the given book. Figure 12-9 shows the main steps for the processing of this assignment.

Figure 12-9. Interaction between cooperating meta-objects.


The evaluation of the assignment of the new price to the price field is performed by sending a message atIV:of:put: to the meta-object linked to the bookA book. The first parameter of this message is the index of the accessed field (we suppose that price is the first field of the class Book), the second parameter is the object holding the field, and the last parameter is the new value. Note that the message metaObject allows the retrieval of the meta-object linked to some base object.

In the case of the bookA object, its direct meta-object is synchroMetaA, which is in charge of synchronization.

When synchroMetaA receives the atIV:of:put: message (step 1 in Figure 12-9), it first locks field access to other threads. Then it requests the next meta-object in the cooperation chain to perform the field access (step 2 in Figure 12-9). The next meta-object in the chain is persistenceMetaA, which enforces persistence. When this latter meta-object receives the atIV:of:put:, it updates the database with the new price. Then it requests the next meta-object in the cooperation chain to perform the field access (step 3 in Figure 12-9). The next meta-object is defaultMeta, which provides the default semantics for the MetaclassTalk MOP. It is defaultMeta that actually writes the new value into the price field. Once the price value is updated, the control flow goes back through the inverse path (defaultMeta, persistenceMeta, and then synchroMeta). So, synchroMeta is given the opportunity to release the lock on accesses to the price field.

As stated above, the meta-object cooperation policy presented here is not the only possible one. Many other strategies to perform meta-object cooperation (and hence deal with conflicting aspects) are possible. One can even imagine a completely different approach for weaving. Instead of doing it at the instance (meta-object) level, it is possible to do it at the level of meta-object classes. In this context, each base object is controlled by a single meta-object. The latter is an instance of a class that "merges" definitions provided by classes related to aspects relevant to the base object. The "merge," for example, can rely on multiple inheritance or mixin-based inheritance [4].

To conclude this section, we should recall that aspect weaving (and particularly weaving non-orthogonal aspects) is still an open issue in AOP [6, 13, 14]. Although reflection does not solve or even avoid possible conflicts, it has two advantages: (1) it expresses the aspect weaving issue in a more familiar way, which is object or class composition, and (2) it makes possible the exploration of various strategies for weaving and conflict handling.



Aspect-Oriented Software Development
Aspect-Oriented Software Development with Use Cases
ISBN: 0321268881
EAN: 2147483647
Year: 2003
Pages: 307

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net