An aspect displays polymorphic behavior in different aspect instances, not just in different join points. Aspects are by default issingleton, but they may be declared perthis, pertarget, percflow, and percflowbelow.
The idea behind environmental advice is that the advice which is applied depends on the aspect instance that is dynamically available at the context of a given point in the execution of the program.
Consider the following Percflow aspect:
(Listing Percflow.java)
abstract aspect Percflow extends SimpleTracing percflow(tracePoints()) {}and two of its concrete subaspects, PerLine and PerPoint:
(Listing PerLine.java)
aspect PerLine extends Percflow { pointcut tracePoints(): call(void Line.incrXY(int,int)); protected void trace(JoinPoint jp) { System.out.println("PerLine instance: " + this); } }
(Listing PerPoint.java)
aspect PerPoint extends Percflow { pointcut tracePoints(): call(void Point.incrXY(int,int)); protected void trace(JoinPoint jp) { System.out.println("PerPoint instance: " + this); } }At a particular point in the execution, there are now many aspect instances (stack based) to chose from. An advice can access the innermost aspect instance by the static method aspectOf(), for example,
PerPoint.aspectOf().trace(thisJoinPoint);This allows polymorphic access to an aspect instance, (even without dynamic dispatch on advice). Unfortunately, AspectJ does not permit you to access the aspect object via the abstract aspect. Attempting to write:
Percflow.aspectOf().trace(thisJoinPoint);would yield a compile time error (saying that no method named aspectOf defined in Percflow.) Hence, this kind of polymorphism is not available today in AspectJ.
Note that the lack of polymorphic support here cannot be worked around by a simple explicit switch statement. Writing:
if (PerPoint.hasAspect()) PerPoint.aspectOf().trace(thisJoinPoint); else if (PerLine.hasAspect()) PerLine.aspectOf().trace(thisJoinPoint); else System.out.println("no Percflow aspect");won't necessarily select the innermost Percflow instance, because a Line can be nested within the control flow of a Point. One could also try to write:
(Listing PerFigureElement.java)
aspect PerFigureElement extends SimpleTracing percflow(tracePoints()) { pointcut tracePoints(): call(void Line.incrXY(int,int)) || call(void Point.incrXY(int,int)); protected void trace(JoinPoint jp) { System.out.println("PerFigureElement " + "instance: " + this); } }but then the polymorphic access is gone, for example,
PerFigureElement.aspectOf().trace(thisJoinPoint);will always invoke the same trace method.
A mechanism which supports environmental advice should allow even more flexibility by late association of the aspect instance and the client trying to access it. Such a mechanism cannot rely on having the source code available for preprocessing. (Bytecode weaving, when available, will not solve this problem.) Instead, advice should be subjected to environmental polymorphism [13] and aspects need to be looked up during the late phase. The client will thus be parameterized by the environment in which it happens to run. We use the term environmental advice to denote such a mechanism.
Schüpany et al. [28] mention aspectual polymorphism as an interesting research area to explore, which they borrowed from Minos [26]. They refer to an environmental advice mechanism in which changes in the aspect context during run-time affects the code of aspectized methods, similar to component deployment mechanisms which allow a container to intercept the methods of its component [23]. We have used the term aspectual polymorphism independently in an early draft of this paper [10] in a broader sense: polymorphism in connection with aspects.