aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB
diff options
context:
space:
mode:
authorAlexander Kriegisch <Alexander@Kriegisch.name>2021-07-16 10:48:06 +0700
committerAlexander Kriegisch <Alexander@Kriegisch.name>2024-01-06 10:09:11 +0100
commita6a1dbea46fd4829189b23fb900da6a586a8151a (patch)
treeb6d8a3b4e38e320813566535c6ea4f036fb4ba91 /docs/progGuideDB
parentfa63feda31a6a9656173a63dc057993d98469305 (diff)
downloadaspectj-a6a1dbea46fd4829189b23fb900da6a586a8151a.tar.gz
aspectj-a6a1dbea46fd4829189b23fb900da6a586a8151a.zip
Fix more AsciiDoc links and code blocks (WIP)
- Add Java syntax highlighting to AspectJ and Java files - Add XML syntax highlighting to XML files (Ant, LTW etc.) - Dedent and remove empty lines, where necessary - Enclose in-line line numbers for Java code in /*23*/ comments in order to enable Java formatting Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/progGuideDB')
-rw-r--r--docs/progGuideDB/examples.adoc131
-rw-r--r--docs/progGuideDB/gettingstarted.adoc42
-rw-r--r--docs/progGuideDB/idioms.adoc5
-rw-r--r--docs/progGuideDB/implementation.adoc6
-rw-r--r--docs/progGuideDB/language.adoc115
-rw-r--r--docs/progGuideDB/pitfalls.adoc5
-rw-r--r--docs/progGuideDB/quickreference.adoc314
-rw-r--r--docs/progGuideDB/semantics.adoc310
8 files changed, 402 insertions, 526 deletions
diff --git a/docs/progGuideDB/examples.adoc b/docs/progGuideDB/examples.adoc
index fccd57eff..5b20a1b4e 100644
--- a/docs/progGuideDB/examples.adoc
+++ b/docs/progGuideDB/examples.adoc
@@ -7,35 +7,27 @@ This chapter consists entirely of examples of AspectJ use.
The examples can be grouped into four categories:
-technique
-
-Examples which illustrate how to use one or more features of the
-language.
-
-development
-
-Examples of using AspectJ during the development phase of a project.
-
-production
-
-Examples of using AspectJ to provide functionality in an application.
-
-reusable
-
-Examples of reuse of aspects and pointcuts.
+technique::
+ Examples which illustrate how to use one or more features of the language
+development::
+ Examples of using AspectJ during the development phase of a project
+production::
+ Examples of using AspectJ to provide functionality in an application
+reusable::
+ Examples of reuse of aspects and pointcuts
[[examples-howto]]
=== Obtaining, Compiling and Running the Examples
The examples source code is part of the AspectJ distribution which may
-be downloaded from the AspectJ project page (
-http://eclipse.org/aspectj[] ).
+be downloaded from the https://eclipse.org/aspectj[AspectJ project page].
Compiling most examples is straightforward. Go the `InstallDir/examples`
directory, and look for a `.lst` file in one of the example
subdirectories. Use the `-arglist` option to `ajc` to compile the
example. For instance, to compile the telecom example with billing, type
+[source, text]
....
ajc -argfile telecom/billing.lst
....
@@ -45,11 +37,13 @@ Java archive (`aspectjrt.jar`). You may either set the `CLASSPATH`
environment variable or use the `-classpath` command line option to the
Java interpreter:
+[source, text]
....
(In Unix use a : in the CLASSPATH)
java -classpath ".:InstallDir/lib/aspectjrt.jar" telecom.billingSimulation
....
+[source, text]
....
(In Windows use a ; in the CLASSPATH)
java -classpath ".;InstallDir/lib/aspectjrt.jar" telecom.billingSimulation
@@ -64,7 +58,7 @@ dynamic join points and advice, and with static introduction. Advice
changes an application's behavior. Introduction changes both an
application's behavior and its structure.
-The first example, xref:#examples-joinPoints[Join Points and ], is about
+The first example, xref:#examples-joinPoints[Join Points and `thisJoinPoint`], is about
gathering and using information about the join point that has triggered
some advice. The second example, xref:#examples-roles[Roles and Views],
concerns a crosscutting view of an existing class hierarchy.
@@ -87,6 +81,7 @@ join point. Here, for example, since the only join points picked out by
the pointcut are calls of a certain method, we can get the target value
and one of the argument values of the method calls directly.
+[source, java]
....
before(Point p, int x): target(p)
&& args(x)
@@ -101,6 +96,7 @@ But sometimes the shape of the join point is not so clear. For instance,
suppose a complex application is being debugged, and we want to trace
when any method of some class is executed. The pointcut
+[source, java]
....
pointcut execsInProblemClass(): within(ProblemClass)
&& execution(* *(..));
@@ -124,19 +120,16 @@ point
* the currently executing object
* the target object
* an object encapsulating the static information about the join point.
-This is also available through the special variable
-+
-thisJoinPointStaticPart
-+
-.
+This is also available through the special variable `thisJoinPointStaticPart`.
===== The `Demo` class
The class `tjp.Demo` in `tjp/Demo.java` defines two methods `foo` and
`bar` with different parameter lists and return types. Both are called,
-with suitable arguments, by `Demo`'s `go` method which was invoked from
+with suitable arguments, by ``Demo``'s `go` method which was invoked from
within its `main` method.
+[source, java]
....
public class Demo {
static Demo d;
@@ -168,6 +161,7 @@ This aspect uses around advice to intercept the execution of methods
`foo` and `bar` in `Demo`, and prints out information garnered from
`thisJoinPoint` to the console.
+[source, java]
....
aspect GetInfo {
@@ -207,6 +201,7 @@ aspect GetInfo {
The pointcut `goCut` is defined as
+[source, java]
....
cflow(this(Demo)) && execution(void go())
....
@@ -221,7 +216,7 @@ advised.
The name of the method and that method's defining class are available as
parts of the
-xref:../api/org/aspectj/lang/Signature.html[org.aspectj.lang.Signature]
+xref:../api/org/aspectj/lang/Signature.html[`org.aspectj.lang.Signature`]
object returned by calling `getSignature()` on either `thisJoinPoint` or
`thisJoinPointStaticPart`.
@@ -274,7 +269,7 @@ are provided by AspectJ without having to modify the code for the class
The `Point` class defines geometric points whose interface includes
polar and rectangular coordinates, plus some simple operations to
-relocate points. `Point`'s implementation has attributes for both its
+relocate points. ``Point``'s implementation has attributes for both its
polar and rectangular coordinates, plus flags to indicate which
currently reflect the position of the point. Some operations cause the
polar coordinates to be updated from the rectangular, and some have the
@@ -292,20 +287,21 @@ image:aspects.gif[image]
===== The `CloneablePoint` aspect
-This first aspect is responsible for `Point`'s implementation of the
+This first aspect is responsible for ``Point``'s implementation of the
`Cloneable` interface. It declares that `Point implements Cloneable`
with a `declare parents` form, and also publically declares a
-specialized `Point`'s `clone()` method. In Java, all objects inherit the
+specialized ``Point``'s `clone()` method. In Java, all objects inherit the
method `clone` from the class `Object`, but an object is not cloneable
unless its class also implements the interface `Cloneable`. In addition,
classes frequently have requirements over and above the simple
bit-for-bit copying that `Object.clone` does. In our case, we want to
-update a `Point`'s coordinate systems before we actually clone the
+update a ``Point``'s coordinate systems before we actually clone the
`Point`. So our aspect makes sure that `Point` overrides `Object.clone`
with a new method that does what we want.
We also define a test `main` method in the aspect for convenience.
+[source, java]
....
public aspect CloneablePoint {
@@ -338,7 +334,7 @@ public aspect CloneablePoint {
===== The `ComparablePoint` aspect
-`ComparablePoint` is responsible for `Point`'s implementation of the
+`ComparablePoint` is responsible for ``Point``'s implementation of the
`Comparable` interface.
The interface `Comparable` defines the single method `compareTo` which
@@ -349,11 +345,11 @@ class that implement it.
parents` to declare that `Point implements
Comparable`, and also publically declares the appropriate
`compareTo(Object)` method: A `Point` `p1` is said to be less than
-another `Point``
- p2` if `p1` is closer to the origin.
+another `Point p2` if `p1` is closer to the origin.
We also define a test `main` method in the aspect for convenience.
+[source, java]
....
public aspect ComparablePoint {
@@ -391,8 +387,8 @@ public aspect ComparablePoint {
===== The `HashablePoint` aspect
-Our third aspect is responsible for `Point`'s overriding of `Object`'s
-`equals` and `hashCode` methods in order to make `Point`s hashable.
+Our third aspect is responsible for ``Point``'s overriding of ``Object``'s
+`equals` and `hashCode` methods in order to make ``Point``s hashable.
The method `Object.hashCode` returns an integer, suitable for use as a
hash table key. It is not required that two objects which are not equal
@@ -408,14 +404,15 @@ values, or the same `rho` and `theta` values, not just when they refer
to the same object. We do this by overriding the methods `equals` and
`hashCode` in the class `Point`.
-So `HashablePoint` declares `Point`'s `hashCode` and `equals` methods,
-using `Point`'s rectangular coordinates to generate a hash code and to
+So `HashablePoint` declares ``Point``'s `hashCode` and `equals` methods,
+using ``Point``'s rectangular coordinates to generate a hash code and to
test for equality. The `x` and `y` coordinates are obtained using the
appropriate get methods, which ensure the rectangular coordinates are
up-to-date before returning their values.
And again, we supply a `main` method in the aspect for testing.
+[source, java]
....
public aspect HashablePoint {
@@ -489,6 +486,7 @@ Throughout this example we will use a simple application that contains
only four classes. The application is about shapes. The `TwoDShape`
class is the root of the shape hierarchy:
+[source, java]
....
public abstract class TwoDShape {
protected double x, y;
@@ -512,6 +510,7 @@ public abstract class TwoDShape {
`TwoDShape` has two subclasses, `Circle` and `Square`:
+[source, java]
....
public class Circle extends TwoDShape {
protected double r;
@@ -533,6 +532,7 @@ public class Circle extends TwoDShape {
}
....
+[source, java]
....
public class Square extends TwoDShape {
protected double s; // side
@@ -558,12 +558,14 @@ To run this application, compile the classes. You can do it with or
without ajc, the AspectJ compiler. If you've installed AspectJ, go to
the directory `InstallDir/examples` and type:
+[source, text]
....
ajc -argfile tracing/notrace.lst
....
To run the program, type
+[source, text]
....
java tracing.ExampleMain
....
@@ -571,6 +573,7 @@ java tracing.ExampleMain
(we don't need anything special on the classpath since this is pure Java
code). You should see the following output:
+[source, text]
....
c1.perimeter() = 12.566370614359172
c1.area() = 12.566370614359172
@@ -588,6 +591,7 @@ by writing a `Trace` class that is exactly what we would write if we
didn't have aspects. The implementation is in `version1/Trace.java`. Its
public interface is:
+[source, java]
....
public class Trace {
public static int TRACELEVEL = 0;
@@ -605,8 +609,9 @@ calls, and we would hope we had not forgotten any method. But we can do
that more consistently and reliably with the following aspect (found in
`version1/TraceMyClasses.java`):
+[source, java]
....
-aspect TraceMyClasses {
+public aspect TraceMyClasses {
pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square);
pointcut myConstructor(): myClass() && execution(new(..));
pointcut myMethod(): myClass() && execution(* *(..));
@@ -638,6 +643,7 @@ information, we can get it through `thisJoinPointStaticPart`.
To run this version of tracing, go to the directory
`InstallDir/examples` and type:
+[source, text]
....
ajc -argfile tracing/tracev1.lst
....
@@ -645,6 +651,7 @@ ajc -argfile tracing/tracev1.lst
Running the main method of `tracing.version1.TraceMyClasses` should
produce the output:
+[source, text]
....
--> tracing.TwoDShape(double, double)
<-- tracing.TwoDShape(double, double)
@@ -707,6 +714,7 @@ functionality of `Trace - version1` with the crosscutting support of
`TraceMyClasses - version1`. We end up with a `Trace` aspect (found in
`version2/Trace.java`) with the following public interface
+[source, java]
....
abstract aspect Trace {
@@ -721,6 +729,7 @@ abstract aspect Trace {
In order to use it, we need to define our own subclass that knows about
our application classes, in `version2/TraceMyClasses.java`:
+[source, java]
....
public aspect TraceMyClasses extends Trace {
pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square);
@@ -737,6 +746,7 @@ Notice that we've simply made the pointcut `classes`, that was an
abstract pointcut in the super-aspect, concrete. To run this version of
tracing, go to the directory `examples` and type:
+[source, text]
....
ajc -argfile tracing/tracev2.lst
....
@@ -748,6 +758,7 @@ the same trace information as that from version 1.
The entire implementation of the new `Trace` class is:
+[source, java]
....
abstract aspect Trace {
@@ -869,6 +880,7 @@ bound property protocol.
The `Point` class is a very simple class with trivial getters and
setters, and a simple vector offset method.
+[source, java]
....
class Point {
@@ -908,11 +920,12 @@ class Point {
===== The `BoundPoint` aspect
-The `BoundPoint` aspect is responsible for `Point`'s "beanness". The
+The `BoundPoint` aspect is responsible for ``Point``'s "beanness". The
first thing it does is privately declare that each `Point` has a
`support` field that holds reference to an instance of
`PropertyChangeSupport`.
+[source, java]
....
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this);
....
@@ -923,10 +936,11 @@ passing it `this`, an instance of `Point`. Since the `support` field is
private declared in the aspect, only the code in the aspect can refer to
it.
-The aspect also declares `Point`'s methods for registering and managing
+The aspect also declares ``Point``'s methods for registering and managing
listeners for property change events, which delegate the work to the
property change support object:
+[source, java]
....
public void Point.addPropertyChangeListener(PropertyChangeListener listener){
support.addPropertyChangeListener(listener);
@@ -951,6 +965,7 @@ public void Point.hasListeners(String propertyName) {
The aspect is also responsible for making sure `Point` implements the
`Serializable` interface:
+[source, java]
....
declare parents: Point implements Serializable;
....
@@ -959,13 +974,14 @@ Implementing this interface in Java does not require any methods to be
implemented. Serialization for `Point` objects is provided by the
default serialization method.
-The `setters` pointcut picks out calls to the `Point`'s `set` methods:
+The `setters` pointcut picks out calls to the ``Point``'s `set` methods:
any method whose name begins with "`set`" and takes one parameter. The
around advice on `setters()` stores the values of the `X` and `Y`
properties, calls the original `set` method and then fires the
appropriate property change event according to which set method was
called.
+[source, java]
....
aspect BoundPoint {
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this);
@@ -1025,6 +1041,7 @@ that point: calling its set methods and the offset method. Then it
serializes the point and writes it to a file and then reads it back. The
result of saving and restoring the point is that a new point is created.
+[source, java]
....
class Demo implements PropertyChangeListener {
@@ -1059,6 +1076,7 @@ class Demo implements PropertyChangeListener {
To compile and run this example, go to the examples directory and type:
+[source, text]
....
ajc -argfile bean/files.lst
java bean.Demo
@@ -1093,6 +1111,7 @@ The generic parts of the protocol are the interfaces `Subject` and
view `Observer` objects, and a method for getting data about state
changes:
+[source, java]
....
interface Subject {
void addObserver(Observer obs);
@@ -1105,6 +1124,7 @@ interface Subject {
The `Observer` interface is just as simple, with methods to set and get
`Subject` objects, and a method to call when the subject gets updated.
+[source, java]
....
interface Observer {
void setSubject(Subject s);
@@ -1117,6 +1137,7 @@ The `SubjectObserverProtocol` aspect contains within it all of the
generic parts of the protocol, namely, how to fire the `Observer`
objects' update methods when some state changes in a subject.
+[source, java]
....
abstract aspect SubjectObserverProtocol {
@@ -1157,6 +1178,7 @@ its `Subject`.
`Button` objects extend `java.awt.Button`, and all they do is make sure
the `void click()` method is called whenever a button is clicked.
+[source, java]
....
class Button extends java.awt.Button {
@@ -1187,6 +1209,7 @@ Note that this class knows nothing about being a Subject.
ColorLabel objects are labels that support the void colorCycle() method.
Again, they know nothing about being an observer.
+[source, java]
....
class ColorLabel extends Label {
@@ -1212,6 +1235,7 @@ Finally, the `SubjectObserverProtocolImpl` implements the
subject/observer protocol, with `Button` objects as subjects and
`ColorLabel` objects as observers:
+[source, java]
....
package observer;
@@ -1246,6 +1270,7 @@ all `ColorLabel` objects observing that button will `colorCycle`.
buttons and three observers and links them together as subjects and
observers. So to run the demo, go to the `examples` directory and type:
+[source, text]
....
ajc -argfile observer/files.lst
java observer.Demo
@@ -1303,6 +1328,7 @@ involved in many calls at one time. image:telecom.gif[image]
`Customer` has methods `call`, `pickup`, `hangup` and `merge` for
managing calls.
+[source, java]
....
public class Customer {
@@ -1377,6 +1403,7 @@ connection between customers. It does this with a simple state machine
connections can be observed. Connection is an abstract class with two
concrete subclasses: `Local` and `LongDistance`.
+[source, java]
....
abstract class Connection {
@@ -1422,6 +1449,7 @@ abstract class Connection {
The two kinds of connections supported by our simulation are `Local` and
`LongDistance` connections.
+[source, java]
....
class Local extends Connection {
Local(Customer a, Customer b) {
@@ -1432,6 +1460,7 @@ class Local extends Connection {
}
....
+[source, java]
....
class LongDistance extends Connection {
LongDistance(Customer a, Customer b) {
@@ -1448,6 +1477,7 @@ The source files for the basic system are listed in the file
`basic.lst`. To build and run the basic system, in a shell window, type
these commands:
+[source, text]
....
ajc -argfile telecom/basic.lst
java telecom.BasicSimulation
@@ -1466,6 +1496,7 @@ stopped, and returns their difference when asked for the elapsed time.
The aspect `TimerLog` (below) can be used to cause the start and stop
times to be printed to standard output.
+[source, java]
....
class Timer {
long startTime, stopTime;
@@ -1490,6 +1521,7 @@ class Timer {
The `TimerLog` aspect can be included in a build to get the timer to
announce when it is started and stopped.
+[source, java]
....
public aspect TimerLog {
@@ -1509,6 +1541,7 @@ The `Timing` aspect is declares an inter-type field `totalConnectTime`
for `Customer` to store the accumulated connection time per `Customer`.
It also declares that each `Connection` object has a timer.
+[source, java]
....
public long Customer.totalConnectTime = 0;
private Timer Connection.timer = new Timer();
@@ -1518,6 +1551,7 @@ Two pieces of after advice ensure that the timer is started when a
connection is completed and and stopped when it is dropped. The pointcut
`endTiming` is defined so that it can be used by the `Billing` aspect.
+[source, java]
....
public aspect Timing {
@@ -1556,10 +1590,11 @@ responsible to pay for it. It also declares the inter-type method
charged differently. The call charge must be calculated after the timer
is stopped; the after advice on pointcut `Timing.endTiming` does this,
and `Billing` is declared to be more precedent than `Timing` to make
-sure that this advice runs after `Timing`'s advice on the same join
+sure that this advice runs after ``Timing``'s advice on the same join
point. Finally, it declares inter-type methods and fields for `Customer`
to handle the `totalCharge`.
+[source, java]
....
public aspect Billing {
// precedence required to get advice on endtiming in the right order
@@ -1613,6 +1648,7 @@ the method run of the superclass `AbstractSimulation`. This method is
intended to print out the status of the customer, with respect to the
`Timing` feature.
+[source, java]
....
protected void report(Customer c){
Timing t = Timing.aspectOf();
@@ -1626,6 +1662,7 @@ The files timing.lst and billing.lst contain file lists for the timing
and billing configurations. To build and run the application with only
the timing feature, go to the directory examples and type:
+[source, text]
....
ajc -argfile telecom/timing.lst
java telecom.TimingSimulation
@@ -1634,6 +1671,7 @@ java telecom.TimingSimulation
To build and run the application with the timing and billing features,
go to the directory examples and type:
+[source, text]
....
ajc -argfile telecom/billing.lst
java telecom.BillingSimulation
@@ -1669,6 +1707,7 @@ the object whose methods are being traced. This can be achieved in at
least two ways. One way is keep the interface of the methods
`traceEntry` and `traceExit` as it was before,
+[source, java]
....
public static void traceEntry(String str);
public static void traceExit(String str);
@@ -1678,6 +1717,7 @@ In this case, the caller is responsible for ensuring that the string
representation of the object is part of the string given as argument.
So, calls must look like:
+[source, java]
....
Trace.traceEntry("Square.distance in " + toString());
....
@@ -1685,6 +1725,7 @@ Trace.traceEntry("Square.distance in " + toString());
Another way is to enforce the requirement with a second argument in the
trace operations, e.g.
+[source, java]
....
public static void traceEntry(String str, Object obj);
public static void traceExit(String str, Object obj);
@@ -1694,6 +1735,7 @@ In this case, the caller is still responsible for sending the right
object, but at least there is some guarantees that some object will be
passed. The calls will look like:
+[source, java]
....
Trace.traceEntry("Square.distance", this);
....
@@ -1709,6 +1751,7 @@ only a small effect inside the `Trace` class. Here's a partial view at
the implementation of `Trace`, version 3. The differences with respect
to version 2 are stressed in the comments:
+[source, java]
....
abstract aspect Trace {
@@ -1794,6 +1837,7 @@ In fact, esimply excluding the execution join point may not be enough,
if there are calls to other traced methods within it -- in which case,
the restriction should be
+[source, java]
....
&& !cflow(execution(String toString()))
....
@@ -1811,6 +1855,7 @@ every application class.
Finally, to run this version of tracing, go to the directory `examples`
and type:
+[source, text]
....
ajc -argfile tracing/tracev3.lst
....
@@ -1819,12 +1864,14 @@ The file tracev3.lst lists the application classes as well as this
version of the files `Trace.java` and `TraceMyClasses.java`. To run the
program, type
+[source, text]
....
java tracing.version3.TraceMyClasses
....
The output should be:
+[source, text]
....
--> tracing.TwoDShape(double, double)
<-- tracing.TwoDShape(double, double)
diff --git a/docs/progGuideDB/gettingstarted.adoc b/docs/progGuideDB/gettingstarted.adoc
index 0dbb85056..f22c9cefd 100644
--- a/docs/progGuideDB/gettingstarted.adoc
+++ b/docs/progGuideDB/gettingstarted.adoc
@@ -39,7 +39,7 @@ testing and performance tuning of applications. And, in the section
following, xref:#starting-production[Production Aspects], we present
aspects that implement crosscutting functionality common in Java
applications. We will defer discussing a third category of aspects,
-reusable aspects, until xref:language.adoc[The AspectJ Language].
+reusable aspects, until xref:language.adoc#language[The AspectJ Language].
These categories are informal, and this ordering is not the only way to
adopt AspectJ. Some developers may want to use a production aspect right
@@ -56,7 +56,7 @@ language, but this is by no means a complete overview of AspectJ.
The features are presented using a simple figure editor system. A
`Figure` consists of a number of `FigureElements`, which can be either
-`Point`s or `Line`s. The `Figure` class provides factory services. There
+``Point``s or ``Line``s. The `Figure` class provides factory services. There
is also a `Display`. Most example programs later in this chapter are
based on this system as well.
@@ -143,17 +143,19 @@ context_ of the original call join point.
In AspectJ, _pointcuts_ pick out certain join points in the program
flow. For example, the pointcut
+[source, java]
....
call(void Point.setX(int))
....
picks out each join point that is a call to a method that has the
-signature `void Point.setX(int)` - that is, `Point`'s void `setX` method
+signature `void Point.setX(int)` - that is, ``Point``'s void `setX` method
with a single `int` parameter.
A pointcut can be built out of other pointcuts with and, or, and not
(spelled `&&`, `||`, and `!`). For example:
+[source, java]
....
call(void Point.setX(int)) ||
call(void Point.setY(int))
@@ -165,6 +167,7 @@ picks out each join point that is either a call to `setX` or a call to
Pointcuts can identify join points from many different types - in other
words, they can crosscut types. For example,
+[source, java]
....
call(void FigureElement.setXY(int,int)) ||
call(void Point.setX(int)) ||
@@ -182,6 +185,7 @@ crosscutting concern, it is a bit of a mouthful. So AspectJ allows
programmers to define their own named pointcuts with the `pointcut`
form. So the following declares a new, named pointcut:
+[source, java]
....
pointcut move():
call(void FigureElement.setXY(int,int)) ||
@@ -202,6 +206,7 @@ _property-based_ crosscutting. The simplest of these involve using
wildcards in certain fields of the method signature. For example, the
pointcut
+[source, java]
....
call(void Figure.make*(..))
....
@@ -211,16 +216,18 @@ picks out each join point that's a call to a void method defined on
parameters. In our system, this picks out calls to the factory methods
`makePoint` and `makeLine`. The pointcut
+[source, java]
....
call(public * Figure.* (..))
....
-picks out each call to `Figure`'s public methods.
+picks out each call to ``Figure``'s public methods.
But wildcards aren't the only properties AspectJ supports. Another
pointcut, `cflow`, identifies join points based on whether they occur in
the dynamic context of other join points. So
+[source, java]
....
cflow(move())
....
@@ -245,6 +252,7 @@ For example, before advice on a method call join point runs before the
actual method starts running, just after the arguments to the method
call are evaluated.
+[source, java]
....
before(): move() {
System.out.println("about to move");
@@ -260,6 +268,7 @@ of after advice: `after returning`, `after
throwing`, and plain `after` (which runs after returning _or_
throwing, like Java's `finally`).
+[source, java]
....
after() returning: move() {
System.out.println("just successfully moved");
@@ -280,6 +289,7 @@ An advice declaration has a parameter list (like a method) that gives
names to all the pieces of context that it uses. For example, the after
advice
+[source, java]
....
after(FigureElement fe, int x, int y) returning:
...SomePointcut... {
@@ -288,10 +298,11 @@ after(FigureElement fe, int x, int y) returning:
....
uses three pieces of exposed context, a `FigureElement` named fe, and
-two `int`s named x and y.
+two ``int``s named x and y.
The body of the advice uses the names just like method parameters, so
+[source, java]
....
after(FigureElement fe, int x, int y) returning:
...SomePointcut... {
@@ -303,6 +314,7 @@ The advice's pointcut publishes the values for the advice's arguments.
The three primitive pointcuts `this`, `target` and `args` are used to
publish these values. So now we can write the complete piece of advice:
+[source, java]
....
after(FigureElement fe, int x, int y) returning:
call(void FigureElement.setXY(int, int))
@@ -326,6 +338,7 @@ named pointcut is used (by advice, or in another named pointcut), it
publishes its context by name just like the `this`, `target` and `args`
pointcut. So another way to write the above advice is
+[source, java]
....
pointcut setXY(FigureElement fe, int x, int y):
call(void FigureElement.setXY(int, int))
@@ -360,8 +373,9 @@ Suppose we want to have `Screen` objects observe changes to `Point`
objects, where `Point` is an existing class. We can implement this by
writing an aspect declaring that the class Point `Point` has an instance
field, `observers`, that keeps track of the `Screen` objects that are
-observing `Point`s.
+observing ``Point``s.
+[source, java]
....
aspect PointObserving {
private Vector Point.observers = new Vector();
@@ -373,6 +387,7 @@ The `observers` field is private, so only `PointObserving` can see it.
So observers are added or removed with the static methods `addObserver`
and `removeObserver` on the aspect.
+[source, java]
....
aspect PointObserving {
private Vector Point.observers = new Vector();
@@ -391,6 +406,7 @@ Along with this, we can define a pointcut `changes` that defines what we
want to observe, and the after advice defines what we want to do when we
observe a change.
+[source, java]
....
aspect PointObserving {
private Vector Point.observers = new Vector();
@@ -417,7 +433,7 @@ aspect PointObserving {
}
....
-Note that neither `Screen`'s nor `Point`'s code has to be modified, and
+Note that neither ``Screen``'s nor ``Point``'s code has to be modified, and
that all the changes needed to support this new capability are local to
this aspect.
@@ -435,6 +451,7 @@ aspect instances. By default, each aspect is a singleton, so one aspect
instance is created. This means that advice may use non-static fields of
the aspect, if it needs to keep state around:
+[source, java]
....
aspect Logging {
OutputStream logStream = System.err;
@@ -471,6 +488,7 @@ workings of a program. It is a simple tracing aspect that prints a
message at specified method calls. In our figure editor example, one
such aspect might simply trace whenever points are drawn.
+[source, java]
....
aspect SimpleTracing {
pointcut tracedCall():
@@ -487,6 +505,7 @@ advice bodies this variable is bound to an object that describes the
current join point. The effect of this code is to print a line like the
following every time a figure element receives a `draw` method call:
+[source, text]
....
Entering: call(void FigureElement.draw(GraphicsContext))
....
@@ -529,6 +548,7 @@ For example, the following aspect counts the number of calls to the
methods of a `Point` that happen within the control flow of those calls
to `rotate`:
+[source, java]
....
aspect SetsInRotateCounting {
int rotateCount = 0;
@@ -589,6 +609,7 @@ properly do the work they are supposed to.
AspectJ makes it possible to implement pre- and post-condition testing
in modular form. For example, this code
+[source, java]
....
aspect PointBoundsChecking {
@@ -636,6 +657,7 @@ the constraint that only the well-known factory methods can add an
element to the registry of figure elements. Enforcing this constraint
ensures that no figure element is added to the registry more than once.
+[source, java]
....
aspect RegistrationProtection {
@@ -662,6 +684,7 @@ This advice throws a runtime exception at certain join points, but
AspectJ can do better. Using the `declare error` form, we can have the
_compiler_ signal the error.
+[source, java]
....
aspect RegistrationProtection {
@@ -722,6 +745,7 @@ state of the dirty flag and resets it to false. The pointcut `move`
captures all the method calls that can move a figure element. The after
advice on `move` sets the dirty flag whenever an object moves.
+[source, java]
....
aspect MoveTracking {
private static boolean dirty = false;
@@ -807,6 +831,7 @@ modular way. The following code adds after advice that runs only when
the factory methods of `Figure` are called in the control flow of a
method on a `ColorControllingClient`.
+[source, java]
....
aspect ColorControl {
pointcut CCClientCflow(ColorControllingClient client):
@@ -841,6 +866,7 @@ captures the public method calls of the package, and the after advice
runs whenever one of those calls throws an Error. The advice logs that
Error and then the throw resumes.
+[source, java]
....
aspect PublicErrorLogging {
Log log = new Log();
@@ -861,6 +887,7 @@ outermost call into the `com.bigboxco` package and the re-entrant call.
The `cflow` primitive pointcut can be used in a nice way to exclude
these re-entrant calls:
+[source, java]
....
after() throwing (Error e):
publicMethodCall() && !cflow(publicMethodCall()) {
@@ -874,6 +901,7 @@ individual methods handle each of the different kinds of elements that
must be parsed. They have names like `parseMethodDec`, `parseThrows`,
and `parseExpr`.
+[source, java]
....
aspect ContextFilling {
pointcut parse(JavaParser jp):
diff --git a/docs/progGuideDB/idioms.adoc b/docs/progGuideDB/idioms.adoc
index 9bc16c081..8e5f6e43e 100644
--- a/docs/progGuideDB/idioms.adoc
+++ b/docs/progGuideDB/idioms.adoc
@@ -11,6 +11,7 @@ Here's an example of how to enfore a rule that code in the java.sql
package can only be used from one particular package in your system.
This doesn't require any access to code in the java.sql package.
+[source, java]
....
/* Any call to methods or constructors in java.sql */
pointcut restrictedCall():
@@ -27,6 +28,7 @@ declare error: restrictedCall() && illegalSource():
Any call to an instance of a subtype of AbstractFacade whose class is
not exactly equal to AbstractFacade:
+[source, java]
....
pointcut nonAbstract(AbstractFacade af):
call(* *(..))
@@ -37,6 +39,7 @@ pointcut nonAbstract(AbstractFacade af):
If AbstractFacade is an abstract class or an interface, then every
instance must be of a subtype and you can replace this with:
+[source, java]
....
pointcut nonAbstract(AbstractFacade af):
call(* *(..))
@@ -46,6 +49,7 @@ pointcut nonAbstract(AbstractFacade af):
Any call to a method which is defined by a subtype of AbstractFacade,
but which isn't defined by the type AbstractFacade itself:
+[source, java]
....
pointcut callToUndefinedMethod():
call(* AbstractFacade+.*(..))
@@ -55,6 +59,7 @@ pointcut callToUndefinedMethod():
The execution of a method that is defined in the source code for a type
that is a subtype of AbstractFacade but not in AbstractFacade itself:
+[source, java]
....
pointcut executionOfUndefinedMethod():
execution(* *(..))
diff --git a/docs/progGuideDB/implementation.adoc b/docs/progGuideDB/implementation.adoc
index a34324d5f..f7a8f7c7b 100644
--- a/docs/progGuideDB/implementation.adoc
+++ b/docs/progGuideDB/implementation.adoc
@@ -17,6 +17,7 @@ implementations should do tomorrow.
According to the AspectJ language semantics, the declaration
+[source, java]
....
before(): get(int Point.x) { System.out.println("got x"); }
....
@@ -128,6 +129,7 @@ source code. This means that there may be call join points to
`Class.forName` or `StringBuffer.append` from programs that do not, at
first glance, appear to contain such calls:
+[source, java]
....
class Test {
void main(String[] args) {
@@ -158,6 +160,7 @@ be the case. Before advice is allowed.
The second is that the control flow of a handler join point is not
picked out. For example, the following pointcut
+[source, java]
....
cflow(call(void foo()) || handler(java.io.IOException))
....
@@ -173,6 +176,7 @@ This does not restrict programs from placing before advice on handlers
inside _other_ control flows. This advice, for example, is perfectly
fine:
+[source, java]
....
before(): handler(java.io.IOException) && cflow(void parse()) {
System.out.println("about to handle an exception while parsing");
@@ -187,6 +191,7 @@ have fewer such restrictions.
The code for Java initializers, such as the assignment to the field d in
+[source, java]
....
class C {
double d = Math.sqrt(2);
@@ -203,6 +208,7 @@ a super-constructor (as opposed to a `this` constructor), the target
type's initialization code will _not_ be run when that inter-type
constructor is called.
+[source, java]
....
aspect A {
C.new(Object o) {} // implicitly calls super()
diff --git a/docs/progGuideDB/language.adoc b/docs/progGuideDB/language.adoc
index f48cc4290..3aeb5eebd 100644
--- a/docs/progGuideDB/language.adoc
+++ b/docs/progGuideDB/language.adoc
@@ -24,30 +24,31 @@ exposed to the new terminology introduced by AspectJ.
Here's an example of an aspect definition in AspectJ:
-....
- 1 aspect FaultHandler {
- 2
- 3 private boolean Server.disabled = false;
- 4
- 5 private void reportFault() {
- 6 System.out.println("Failure! Please fix it.");
- 7 }
- 8
- 9 public static void fixServer(Server s) {
-10 s.disabled = false;
-11 }
-12
-13 pointcut services(Server s): target(s) && call(public * *(..));
-14
-15 before(Server s): services(s) {
-16 if (s.disabled) throw new DisabledException();
-17 }
-18
-19 after(Server s) throwing (FaultException e): services(s) {
-20 s.disabled = true;
-21 reportFault();
-22 }
-23 }
+[source, java]
+....
+/*01*/ aspect FaultHandler {
+/*02*/
+/*03*/ private boolean Server.disabled = false;
+/*04*/
+/*05*/ private void reportFault() {
+/*06*/ System.out.println("Failure! Please fix it.");
+/*07*/ }
+/*08*/
+/*09*/ public static void fixServer(Server s) {
+/*10*/ s.disabled = false;
+/*11*/ }
+/*12*/
+/*13*/ pointcut services(Server s): target(s) && call(public * *(..));
+/*14*/
+/*15*/ before(Server s): services(s) {
+/*16*/ if (s.disabled) throw new DisabledException();
+/*17*/ }
+/*18*/
+/*19*/ after(Server s) throwing (FaultException e): services(s) {
+/*20*/ s.disabled = true;
+/*21*/ reportFault();
+/*22*/ }
+/*23*/ }
....
The `FaultHandler` consists of one inter-type field on `Server` (line
@@ -69,6 +70,7 @@ invocations and executions, the handling of exceptions, field
assignments and accesses, etc. Take, for example, the pointcut
definition in line 13:
+[source, java]
....
pointcut services(Server s): target(s) && call(public * *(..))
....
@@ -114,6 +116,7 @@ define aspect implementation that runs at join points picked out by the
pointcut. For example, the advice in lines 15-17 specifies that the
following piece of code
+[source, java]
....
{
if (s.disabled) throw new DisabledException();
@@ -128,6 +131,7 @@ corresponding methods are executed.
The advice in lines 19-22 defines another piece of implementation that
is executed on the same pointcut:
+[source, java]
....
{
s.disabled = true;
@@ -148,6 +152,7 @@ this guide.
Consider the following Java class:
+[source, java]
....
class Point {
private int x, y;
@@ -166,6 +171,7 @@ In order to get an intuitive understanding of AspectJ's join points and
pointcuts, let's go back to some of the basic principles of Java.
Consider the following a method declaration in class Point:
+[source, java]
....
void setX(int x) { this.x = x; }
....
@@ -192,6 +198,7 @@ complete listing.)
Pointcuts pick out these join points. For example, the pointcut
+[source, java]
....
pointcut setter(): target(Point) &&
(call(void setX(int)) ||
@@ -201,6 +208,7 @@ pointcut setter(): target(Point) &&
picks out each call to `setX(int)` or `setY(int)` when called on an
instance of `Point`. Here's another example:
+[source, java]
....
pointcut ioHandler(): within(MyClass) && handler(IOException);
....
@@ -230,7 +238,7 @@ when the target object is of type `SomeType`::
`target(SomeType)`
when the executing code belongs to class `MyClass`::
`within(MyClass)`
-when the join point is in the control flow of a call to a `Test`'s
+when the join point is in the control flow of a call to a ``Test``'s
no-argument `main` method::
`cflow(call(void Test.main()))`
@@ -256,9 +264,9 @@ such `set` method; this pointcut picks out calls to all of them.
means (1) the execution of any method with no parameters that returns an
`int`, (2) the call to any `setY` method that takes a `long` as an
argument, regardless of return type or declaring type, (3) the call to
-any of `Point`'s `setY` methods that take an `int` as an argument,
+any of ``Point``'s `setY` methods that take an `int` as an argument,
regardless of return type, and (4) the call to any classes' constructor,
-so long as it takes exactly two `int`s as arguments.
+so long as it takes exactly two ``int``s as arguments.
* You can compose pointcuts. For example,
[arabic]
. `target(Point) && call(int *())`
@@ -270,7 +278,7 @@ so long as it takes exactly two `int`s as arguments.
+
means (1) any call to an `int` method with no arguments on an instance
of `Point`, regardless of its name, (2) any call to any method where the
-call is made from the code in `Point`'s or `Line`'s type declaration,
+call is made from the code in ``Point``'s or ``Line``'s type declaration,
(3) the execution of any constructor taking exactly one `int` argument,
regardless of where the call is made from, and (4) any method call to an
`int` method when the executing object is any type except `Point`.
@@ -286,12 +294,13 @@ non-static method, and (3) any execution of a public, non-static method.
* Pointcuts can also deal with interfaces. For example, given the
interface
+
+[source, java]
....
interface MyInterface { ... }
....
+
the pointcut `call(* MyInterface.*(..))` picks out any call to a method
-in `MyInterface`'s signature -- that is, any method defined by
+in ``MyInterface``'s signature -- that is, any method defined by
`MyInterface` or inherited by one of its a supertypes.
[[call-vs-execution]]
@@ -339,6 +348,7 @@ primitive pointcuts like `cflow` and `cflowbelow`. Here's an example:
`cflow(P)` picks out each join point in the control flow of the join
points picked out by <P>. So, pictorially:
+[source, text]
....
P ---------------------
\
@@ -350,6 +360,7 @@ What does `cflow(P) &&
cflow(Q)` pick out? Well, it picks out each join point that is
in both the control flow of <P> and in the control flow of <Q>. So...
+[source, text]
....
P ---------------------
\
@@ -370,6 +381,7 @@ But what does `cflow(P
&& Q)` mean? Well, it means the control flow of those join
points that are both picked out by <P> and picked out by <Q>.
+[source, text]
....
P && Q -------------------
\
@@ -384,6 +396,7 @@ control flow of `(P &&
Here's some code that expresses this.
+[source, java]
....
public class Test {
public static void main(String[] args) {
@@ -422,6 +435,7 @@ for more details.)
Consider again the first pointcut definition in this chapter:
+[source, java]
....
pointcut setter(): target(Point) &&
(call(void setX(int)) ||
@@ -435,6 +449,7 @@ side. An empty parameter list means that none of the context from the
join points is published from this pointcut. But consider another
version of version of this pointcut definition:
+[source, java]
....
pointcut setter(Point p): target(p) &&
(call(void setX(int)) ||
@@ -452,6 +467,7 @@ matched join point.
Here's another example that illustrates the flexible mechanism for
defining pointcut parameters:
+[source, java]
....
pointcut testEquality(Point p): target(Point) &&
args(p) &&
@@ -464,10 +480,11 @@ access to a `Point` from each join point. But in this case, looking at
the right-hand side we find that the object named in the parameters is
not the target `Point` object that receives the call; it's the argument
(also of type `Point`) passed to the `equals` method when some other
-`Point` is the target. If we wanted access to both `Point`s, then the
+`Point` is the target. If we wanted access to both ``Point``s, then the
pointcut definition that would expose target `Point p1` and argument
`Point p2` would be
+[source, java]
....
pointcut testEquality(Point p1, Point p2): target(p1) &&
args(p2) &&
@@ -476,6 +493,7 @@ pointcut testEquality(Point p1, Point p2): target(p1) &&
Let's look at another variation of the `setters` pointcut:
+[source, java]
....
pointcut setter(Point p, int newval): target(p) &&
args(newval) &&
@@ -493,6 +511,7 @@ important rule is that all the pointcut parameters must be bound at
every join point picked out by the pointcut. So, for example, the
following pointcut definition will result in a compilation error:
+[source, java]
....
pointcut badPointcut(Point p1, Point p2):
(target(p1) && call(void setX(int))) ||
@@ -512,6 +531,7 @@ operations to their `Partner` objects. The aspect `HandleLiveness`
ensures that, before the delegations, the partner exists and is alive,
or else it throws an exception.
+[source, java]
....
class Handle {
Partner partner = new Partner();
@@ -594,6 +614,7 @@ given either by named pointcuts (like the ones you've seen above) or by
anonymous pointcuts. Here is an example of an advice on a named
pointcut:
+[source, java]
....
pointcut setter(Point p1, int newval): target(p1) && args(newval)
(call(void setX(int) ||
@@ -607,6 +628,7 @@ before(Point p1, int newval): setter(p1, newval) {
And here is exactly the same example, but using an anonymous pointcut:
+[source, java]
....
before(Point p1, int newval): target(p1) && args(newval)
(call(void setX(int)) ||
@@ -621,6 +643,7 @@ Here are examples of the different advice:
This before advice runs just before the join points picked out by the
(anonymous) pointcut:
+[source, java]
....
before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
if (!p.assertX(x)) return;
@@ -631,6 +654,7 @@ This after advice runs just after each join point picked out by the
(anonymous) pointcut, regardless of whether it returns normally or
throws an exception:
+[source, java]
....
after(Point p, int x): target(p) && args(x) && call(void setX(int)) {
if (!p.assertX(x)) throw new PostConditionViolation();
@@ -642,6 +666,7 @@ by the (anonymous) pointcut, but only if it returns normally. The return
value can be accessed, and is named `x` here. After the advice runs, the
return value is returned:
+[source, java]
....
after(Point p) returning(int x): target(p) && call(int getX()) {
System.out.println("Returning int value " + x + " for p = " + p);
@@ -653,6 +678,7 @@ the (anonymous) pointcut, but only when it throws an exception of type
`Exception`. Here the exception value can be accessed with the name `e`.
The advice re-raises the exception after it's done:
+[source, java]
....
after() throwing(Exception e): target(Point) && call(void setX(int)) {
System.out.println(e);
@@ -663,6 +689,7 @@ This around advice traps the execution of the join point; it runs
_instead_ of the join point. The original action associated with the
join point can be invoked through the special `proceed` call:
+[source, java]
....
void around(Point p, int x): target(p)
&& args(x)
@@ -683,6 +710,7 @@ class. Here are examples of some such inter-type declarations:
This declares that each `Server` has a `boolean` field named `disabled`,
initialized to `false`:
+[source, java]
....
private boolean Server.disabled = false;
....
@@ -696,6 +724,7 @@ another aspect) there won't be a name collision, since no reference to
This declares that each `Point` has an `int` method named `getX` with no
arguments that returns whatever `this.x` is:
+[source, java]
....
public int Point.getX() { return this.x; }
....
@@ -707,6 +736,7 @@ conflict.
This publically declares a two-argument constructor for `Point`:
+[source, java]
....
public Point.new(int x, int y) { this.x = x; this.y = y; }
....
@@ -714,6 +744,7 @@ public Point.new(int x, int y) { this.x = x; this.y = y; }
This publicly declares that each `Point` has an `int` field named `x`,
initialized to zero:
+[source, java]
....
public int Point.x = 0;
....
@@ -724,6 +755,7 @@ has a field named `x` (defined by `Point` or by another aspect).
This declares that the `Point` class implements the `Comparable`
interface:
+[source, java]
....
declare parents: Point implements Comparable;
....
@@ -734,6 +766,7 @@ required by `Comparable`.
This declares that the `Point` class extends the `GeometricObject`
class.
+[source, java]
....
declare parents: Point extends GeometricObject;
....
@@ -741,6 +774,7 @@ declare parents: Point extends GeometricObject;
An aspect can have several inter-type declarations. For example, the
following declarations
+[source, java]
....
public String Point.name;
public void Point.setName(String name) { this.name = name; }
@@ -754,6 +788,7 @@ An inter-type member can only have one target type, but often you may
wish to declare the same member on more than one type. This can be done
by using an inter-type member in combination with a private interface:
+[source, java]
....
aspect A {
private interface HasName {}
@@ -782,18 +817,20 @@ declarations in addition to public inter-type declarations. Private
means private in relation to the aspect, not necessarily the target
type. So, if an aspect makes a private inter-type declaration of a field
+[source, java]
....
private int Foo.x;
....
-Then code in the aspect can refer to `Foo`'s `x` field, but nobody else
+Then code in the aspect can refer to ``Foo``'s `x` field, but nobody else
can. Similarly, if an aspect makes a package-protected introduction,
+[source, java]
....
- int Foo.x;
+int Foo.x;
....
-then everything in the aspect's package (which may or may not be `Foo`'s
+then everything in the aspect's package (which may or may not be ``Foo``'s
package) can access `x`.
==== Example: `PointAssertions`
@@ -806,6 +843,7 @@ other parts of the program (including the code in `Point`) have no
business accessing the assert methods. Only the code inside of the
aspect can call those methods.
+[source, java]
....
class Point {
int x, y;
@@ -856,6 +894,7 @@ One way to use it is simply to print it out. Like all Java objects,
`thisJoinPoint` has a `toString()` method that makes quick-and-dirty
tracing easy:
+[source, java]
....
aspect TraceNonStaticMethods {
before(Point p): target(p) && call(* *(..)) {
@@ -868,6 +907,7 @@ The type of `thisJoinPoint` includes a rich reflective class hierarchy
of signatures, and can be used to access both static and dynamic
information about join points such as the arguments of the join point:
+[source, java]
....
thisJoinPoint.getArgs()
....
@@ -876,6 +916,7 @@ In addition, it holds an object consisting of all the static information
about the join point such as corresponding line number and static
signature:
+[source, java]
....
thisJoinPoint.getStaticPart()
....
@@ -888,6 +929,7 @@ necessary when using `thisJoinPoint` directly.
It is always the case that
+[source, java]
....
thisJoinPointStaticPart == thisJoinPoint.getStaticPart()
@@ -903,8 +945,9 @@ but it is not the current but the enclosing join point. So, for example,
it is possible to print out the calling source location (if available)
with
+[source, java]
....
- before() : execution (* *(..)) {
- System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation())
- }
+before() : execution (* *(..)) {
+ System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation())
+}
....
diff --git a/docs/progGuideDB/pitfalls.adoc b/docs/progGuideDB/pitfalls.adoc
index b1769ce26..0bbe6f5f5 100644
--- a/docs/progGuideDB/pitfalls.adoc
+++ b/docs/progGuideDB/pitfalls.adoc
@@ -11,6 +11,7 @@ surprising behavior and how to understand them.
Here is a Java program with peculiar behavior
+[source, java]
....
public class Main {
public static void main(String[] args) {
@@ -39,6 +40,7 @@ the completely silent abort.
The following short aspect will also generate this behavior:
+[source, java]
....
aspect A {
before(): call(* *(..)) { System.out.println("before"); }
@@ -50,6 +52,7 @@ Why? Because the call to println is also a call matched by the pointcut
`call (* *(..))`. We get no output because we used simple after()
advice. If the aspect were changed to
+[source, java]
....
aspect A {
before(): call(* *(..)) { System.out.println("before"); }
@@ -65,6 +68,7 @@ There's a simple idiom to use if you ever have a worry that your advice
might apply in this way. Just restrict the advice from occurring in join
points caused within the aspect. So:
+[source, java]
....
aspect A {
before(): call(* *(..)) && !within(A) { System.out.println("before"); }
@@ -75,6 +79,7 @@ aspect A {
Other solutions might be to more closely restrict the pointcut in other
ways, for example:
+[source, java]
....
aspect A {
before(): call(* MyObject.*(..)) { System.out.println("before"); }
diff --git a/docs/progGuideDB/quickreference.adoc b/docs/progGuideDB/quickreference.adoc
index 01b152e31..6d8febc56 100644
--- a/docs/progGuideDB/quickreference.adoc
+++ b/docs/progGuideDB/quickreference.adoc
@@ -9,16 +9,16 @@
|*Methods and Constructors* |
|`call(Signature)` |every call to any method or constructor matching
-<Signature> at the call site
+`<Signature>` at the call site
|`execution(Signature)` |every execution of any method or constructor
-matching <Signature>
+matching `<Signature>`
|*Fields* |
-|`get(Signature)` |every reference to any field matching <Signature>
+|`get(Signature)` |every reference to any field matching `<Signature>`
-|`set(Signature)` |every assignment to any field matching <Signature>.
+|`set(Signature)` |every assignment to any field matching `<Signature>`.
The assigned value can be exposed with an `args` pointcut
|*Exception Handlers* |
@@ -37,12 +37,12 @@ pointcut
initializer for any type in <TypePattern>
|`initialization(Signature)` |every initialization of an object when the
-first constructor called in the type matches <Signature>, encompassing
+first constructor called in the type matches `<Signature>`, encompassing
the return from the super constructor call to the return of the
first-called constructor
|`preinitialization(Signature)` |every pre-initialization of an object
-when the first constructor called in the type matches <Signature>,
+when the first constructor called in the type matches `<Signature>`,
encompassing the entry of the first-called constructor to the call to
the super constructor
@@ -52,7 +52,7 @@ the super constructor
<TypePattern>
|`withincode(Signature)` |every join point from code defined in a method
-or constructor matching <Signature>
+or constructor matching `<Signature>`
|===
[[quick-typePatterns]]
@@ -62,290 +62,118 @@ A type pattern is one of
[cols=",",]
|===
-|<TypeNamePattern> |all types in <TypeNamePattern>
+|*Type pattern* |
-|<SubtypePattern> |all types in <SubtypePattern>, a pattern with a +.
+|`<TypeNamePattern>` |all types in `<TypeNamePattern>`
-|<ArrayTypePattern> |all types in <ArrayTypePattern>, a pattern with one
-or more []s.
+|`<SubtypePattern>` |all types in `<SubtypePattern>`, a pattern with a `+`
+
+|`<ArrayTypePattern>` |all types in `<ArrayTypePattern>`, a pattern with one or more ``[]``s.
|`!TypePattern` |all types not in <TypePattern>
-|`TypePattern0
- && TypePattern1` |all types in both <TypePattern0> and
-<TypePattern1>
+|`TypePattern0 && TypePattern1` |all types in both `<TypePattern0>` and `<TypePattern1>`
-|`TypePattern0 || TypePattern1` |all types in either <TypePattern0> or
-<TypePattern1>
+|`TypePattern0 \|\| TypePattern1` |all types in either `<TypePattern0>` or `<TypePattern1>`
-|`( TypePattern )` |all types in <TypePattern>
+|`( TypePattern )` |all types in `<TypePattern>`
|===
-where <TypeNamePattern> can either be a plain type name, the wildcard
-`*` (indicating all types), or an identifier with embedded `*` and `..`
+where `<TypeNamePattern>` can either be a plain type name, the wildcard
+`\*` (indicating all types), or an identifier with embedded `*` and `..`
wildcards.
An embedded `*` in an identifier matches any sequence of characters, but
-does not match the package (or inner-type) separator ".".
+does not match the package (or inner-type) separator `.`.
An embedded `..` in an identifier matches any sequence of characters
-that starts and ends with the package (or inner-type) separator ".".
+that starts and ends with the package (or inner-type) separator `.`.
[[quick-advice]]
=== Advice
Each piece of advice is of the form
-____
-[ strictfp ]
-
-AdviceSpec
-
-[ throws
-
-TypeList
-
-] :
-
-Pointcut
+[source, text]
+....
+[ strictfp ] AdviceSpec [ throws TypeList ] : Pointcut { Body }
+....
-\{
+where `<AdviceSpec>` is one of
-Body
-
-}
-____
-
-where <AdviceSpec> is one of
-
-`before( Formals ) `::
+`before( Formals )`::
runs before each join point
-`after( Formals ) returning
- [ ( Formal ) ] `::
+`after( Formals ) returning [ ( Formal ) ]`::
runs after each join point that returns normally. The optional formal
gives access to the returned value
-`after( Formals ) throwing [
- ( Formal ) ] `::
- runs after each join point that throws a
- +
- Throwable
- +
- . If the optional formal is present, runs only after each join point
- that throws a
- +
- Throwable
- +
- of the type of
- +
- Formal
- +
- , and
- +
- Formal
- +
- gives access to the
- +
- Throwable
- +
- exception value
-`after( Formals ) `::
+`after( Formals ) throwing [ ( Formal ) ]`::
+ runs after each join point that throws a `Throwable`.
+ If the optional formal is present, runs only after each join point
+ that throws a `Throwable` of the type of `Formal`, and `Formal` gives access to the
+ `Throwable` exception value
+`after( Formals )`::
runs after each join point regardless of whether it returns normally
- or throws a
- +
- Throwable
-`Type
- around( Formals ) `::
+ or throws a `Throwable`
+`Type around( Formals )`::
runs in place of each join point. The join point can be executed by
- calling
- +
- proceed
- +
- , which takes the same number and types of arguments as the around
+ calling `proceed`, which takes the same number and types of arguments as the around
advice.
Three special variables are available inside of advice bodies:
`thisJoinPoint`::
- an object of type
- +
- org.aspectj.lang.JoinPoint
- +
- representing the join point at which the advice is executing.
+ an object of type `org.aspectj.lang.JoinPoint` representing the join point
+ at which the advice is executing
`thisJoinPointStaticPart`::
- equivalent to
- +
- thisJoinPoint.getStaticPart()
- +
- , but may use fewer runtime resources.
+ equivalent to `thisJoinPoint.getStaticPart()`, but may use fewer runtime resources
`thisEnclosingJoinPointStaticPart`::
- the static part of the dynamically enclosing join point.
+ the static part of the dynamically enclosing join point
[[quick-interType]]
=== Inter-type member declarations
Each inter-type member is one of
-`
- Modifiers ReturnType OnType . Id
- ( Formals )
- [ throws TypeList ]
- { Body }
- `::
- a method on
- +
- OnType
- +
- .
-`
- abstract Modifiers ReturnType OnType . Id
- ( Formals )
- [ throws TypeList ] ;
- `::
- an abstract method on
- +
- OnType
- +
- .
-`
- Modifiers OnType . new
- ( Formals )
- [ throws TypeList ]
- { Body }
- `::
- a constructor on
- +
- OnType
- +
- .
-`
- Modifiers Type OnType . Id
- [ = Expression ] ;
- `::
- a field on
- +
- OnType
- +
- .
+`Modifiers ReturnType OnType . Id ( Formals ) [ throws TypeList ] { Body }`::
+ a method on `OnType`
+`abstract Modifiers ReturnType OnType . Id ( Formals ) [ throws TypeList ] ;`::
+ an abstract method on `OnType`
+`Modifiers OnType . new ( Formals ) [ throws TypeList ] { Body }`::
+ a constructor on `OnType`
+`Modifiers Type OnType . Id [ = Expression ] ;`::
+ a field on `OnType`
[[quick-other]]
=== Other declarations
-`
- declare parents :
- TypePattern extends
- Type ;
- `::
- the types in
- +
- TypePattern
- +
- extend
- +
- Type
- +
- .
-`
- declare parents : TypePattern
- implements TypeList ;
- `::
- the types in
- +
- TypePattern
- +
- implement the types in
- +
- TypeList
- +
- .
-`
- declare warning : Pointcut :
- String ;
- `::
- if any of the join points in
- +
- Pointcut
- +
- possibly exist in the program, the compiler emits the warning
- +
- String
- +
- .
-`
- declare error : Pointcut :
- String ;
- `::
- if any of the join points in
- +
- Pointcut
- +
- could possibly exist in the program, the compiler emits the error
- +
- String
- +
- .
-`
- declare soft :
- Type :
- Pointcut ;
- `::
- any
- +
- Type
- +
- exception that gets thrown at any join point picked out by
- +
- Pointcut
- +
- is wrapped in
- +
- org.aspectj.lang.SoftException
- +
- .
-`
- declare precedence :
- TypePatternList ;
- `::
+`declare parents : TypePattern extends Type ;`::
+ the types in `TypePattern` extend `Type`
+`declare parents : TypePattern implements TypeList ;`::
+ the types in `TypePattern` implement the types in `TypeList`
+`declare warning : Pointcut : String ;`::
+ if any of the join points in `Pointcut` possibly exist in the program,
+ the compiler emits the warning `String`
+`declare error : Pointcut : String ;`::
+ if any of the join points in `Pointcut` could possibly exist in the program,
+ the compiler emits the error `String`
+`declare soft : Type : Pointcut ;`::
+ any `Type` exception that gets thrown at any join point picked out by `Pointcut`
+ is wrapped in `org.aspectj.lang.SoftException`
+`declare precedence : TypePatternList ;`::
at any join point where multiple pieces of advice apply, the advice
- precedence at that join point is in
- +
- TypePatternList
- +
- order.
+ precedence at that join point is in `TypePatternList` order
[[quick-aspectAssociations]]
=== Aspects
Each aspect is of the form
-____
-[ privileged ]
-
-Modifiers
-
-aspect
-
-Id
-
-[ extends
-
-Type
-
-] [ implements
-
-TypeList
-
-] [
-
-PerClause
-
-] \{
-
-Body
-
-}
-____
+[source, text]
+....
+[ privileged ] Modifiers aspect Id [ extends Type ] [ implements TypeList ] [ PerClause ] { Body }
+....
-where <PerClause> defines how the aspect is instantiated and associated
+where `<PerClause>` defines how the aspect is instantiated and associated
(`issingleton()` by default):
[cols=",,",options="header",]
@@ -355,18 +183,18 @@ where <PerClause> defines how the aspect is instantiated and associated
default. |`aspectOf()` at all join points
|`perthis(Pointcut)` |An instance is associated with each object that is
-the currently executing object at any join point in <Pointcut>.
+the currently executing object at any join point in `<Pointcut>`.
|`aspectOf(Object)` at all join points
|`pertarget(Pointcut)` |An instance is associated with each object that
-is the target object at any join point in <Pointcut>.
+is the target object at any join point in `<Pointcut>`.
|`aspectOf(Object)` at all join points
|`percflow(Pointcut)` |The aspect is defined for each entrance to the
-control flow of the join points defined by <Pointcut>. |`aspectOf()` at
+control flow of the join points defined by `<Pointcut>`. |`aspectOf()` at
join points in `cflow(Pointcut)`
|`percflowbelow(Pointcut)` |The aspect is defined for each entrance to
-the control flow below the join points defined by <Pointcut>.
+the control flow below the join points defined by `<Pointcut>`.
|`aspectOf()` at join points in `cflowbelow(Pointcut)`
|===
diff --git a/docs/progGuideDB/semantics.adoc b/docs/progGuideDB/semantics.adoc
index 1943aa609..aa46cf18d 100644
--- a/docs/progGuideDB/semantics.adoc
+++ b/docs/progGuideDB/semantics.adoc
@@ -63,11 +63,7 @@ Constructor call::
Constructor execution::
When the body of code for an actual constructor executes, after its
this or super constructor call. The object being constructed is the
- currently executing object, and so may be accessed with the
- +
- this
- +
- pointcut. The constructor execution join point for a constructor that
+ currently executing object, and so may be accessed with the `_this_` pointcut. The constructor execution join point for a constructor that
calls a super constructor also includes any non-static initializers of
enclosing class. No value is returned from a constructor execution
join point, so its return type is considered to be void.
@@ -80,15 +76,7 @@ Object pre-initialization::
This encompasses the time between the start of its first called
constructor and the start of its parent's constructor. Thus, the
execution of these join points encompass the join points of the
- evaluation of the arguments of
- +
- this()
- +
- and
- +
- super()
- +
- constructor calls. No value is returned from an object
+ evaluation of the arguments of `_this()_` and `_super()_` constructor calls. No value is returned from an object
pre-initialization join point, so its return type is considered to be
void.
Object initialization::
@@ -97,11 +85,7 @@ Object initialization::
and the return of its first called constructor. It includes all the
dynamic initializers and constructors used to create the object. The
object being constructed is the currently executing object, and so may
- be accessed with the
- +
- this
- +
- pointcut. No value is returned from a constructor execution join
+ be accessed with the `_this_` pointcut. No value is returned from a constructor execution join
point, so its return type is considered to be void.
Field reference::
When a non-constant field is referenced. [Note that references to
@@ -180,219 +164,84 @@ build up other pointcuts. The primitive pointcuts and combinators
provided by the language are:
`call(MethodPattern)`::
- Picks out each method call join point whose signature matches
- +
- MethodPattern
- +
- .
+ Picks out each method call join point whose signature matches `_MethodPattern_`.
`execution(MethodPattern)`::
- Picks out each method execution join point whose signature matches
- +
- MethodPattern
- +
- .
+ Picks out each method execution join point whose signature matches `_MethodPattern_`.
`get(FieldPattern)`::
- Picks out each field reference join point whose signature matches
- +
- FieldPattern
- +
- . [Note that references to constant fields (static final fields bound
+ Picks out each field reference join point whose signature matches `_FieldPattern_`. [Note that references to constant fields (static final fields bound
to a constant string object or primitive value) are not join points,
since Java requires them to be inlined.]
`set(FieldPattern)`::
- Picks out each field set join point whose signature matches
- +
- FieldPattern
- +
- . [Note that the initializations of constant fields (static final
+ Picks out each field set join point whose signature matches `_FieldPattern_`. [Note that the initializations of constant fields (static final
fields where the initializer is a constant string object or primitive
value) are not join points, since Java requires their references to be
inlined.]
`call(ConstructorPattern)`::
- Picks out each constructor call join point whose signature matches
- +
- ConstructorPattern
- +
- .
+ Picks out each constructor call join point whose signature matches `_ConstructorPattern_`.
`execution(ConstructorPattern)`::
Picks out each constructor execution join point whose signature
- matches
- +
- ConstructorPattern
- +
- .
+ matches `_ConstructorPattern_`.
`initialization(ConstructorPattern)`::
Picks out each object initialization join point whose signature
- matches
- +
- ConstructorPattern
- +
- .
+ matches `_ConstructorPattern_`.
`preinitialization(ConstructorPattern)`::
Picks out each object pre-initialization join point whose signature
- matches
- +
- ConstructorPattern
- +
- .
+ matches `_ConstructorPattern_`.
`staticinitialization(TypePattern)`::
Picks out each static initializer execution join point whose signature
- matches
- +
- TypePattern
- +
- .
+ matches `_TypePattern_`.
`handler(TypePattern)`::
- Picks out each exception handler join point whose signature matches
- +
- TypePattern
- +
- .
+ Picks out each exception handler join point whose signature matches `_TypePattern_`.
`adviceexecution()`::
Picks out all advice execution join points.
`within(TypePattern)`::
Picks out each join point where the executing code is defined in a
- type matched by
- +
- TypePattern
- +
- .
+ type matched by `_TypePattern_`.
`withincode(MethodPattern)`::
Picks out each join point where the executing code is defined in a
- method whose signature matches
- +
- MethodPattern
- +
- .
+ method whose signature matches `_MethodPattern_`.
`withincode(ConstructorPattern)`::
Picks out each join point where the executing code is defined in a
- constructor whose signature matches
- +
- ConstructorPattern
- +
- .
+ constructor whose signature matches `_ConstructorPattern_`.
`cflow(Pointcut)`::
- Picks out each join point in the control flow of any join point
- +
- P
- +
- picked out by
- +
- Pointcut
- +
- , including
- +
- P
- +
- itself.
+ Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_` , including `_P_` itself.
`cflowbelow(Pointcut)`::
- Picks out each join point in the control flow of any join point
- +
- P
- +
- picked out by
- +
- Pointcut
- +
- , but not
- +
- P
- +
- itself.
+ Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_`, but not `_P_` itself.
`this(Type or Id)`::
Picks out each join point where the currently executing object (the
- object bound to
- +
- this
- +
- ) is an instance of
- +
- Type
- +
- , or of the type of the identifier
- +
- Id
- +
- (which must be bound in the enclosing advice or pointcut definition).
+ object bound to `_this_`) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition).
Will not match any join points from static contexts.
`target(Type or Id)`::
Picks out each join point where the target object (the object on which
- a call or field operation is applied to) is an instance of
- +
- Type
- +
- , or of the type of the identifier
- +
- Id
- +
- (which must be bound in the enclosing advice or pointcut definition).
+ a call or field operation is applied to) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition).
Will not match any calls, gets, or sets of static members.
`args(Type or Id, ...)`::
Picks out each join point where the arguments are instances of the
- appropriate type (or type of the identifier if using that form). A
- +
- null
- +
- argument is matched iff the static type of the argument (declared
+ appropriate type (or type of the identifier if using that form). A `_null_` argument is matched iff the static type of the argument (declared
parameter type or field type) is the same as, or a subtype of, the
specified args type.
`PointcutId(TypePattern or Id, ...)`::
Picks out each join point that is picked out by the user-defined
- pointcut designator named by
- +
- PointcutId
- +
- .
+ pointcut designator named by `_PointcutId_` .
`if(BooleanExpression)`::
- Picks out each join point where the boolean expression evaluates to
- +
- true
- +
- . The boolean expression used can only access static members,
- parameters exposed by the enclosing pointcut or advice, and
- +
- thisJoinPoint
- +
- forms. In particular, it cannot call non-static methods on the aspect
+ Picks out each join point where the boolean expression evaluates to `_true_` . The boolean expression used can only access static members,
+ parameters exposed by the enclosing pointcut or advice, and `_thisJoinPoint_` forms. In particular, it cannot call non-static methods on the aspect
or use return values or exceptions exposed by after advice.
`! Pointcut`::
- Picks out each join point that is not picked out by
- +
- Pointcut
- +
- .
+ Picks out each join point that is not picked out by `_Pointcut_` .
`Pointcut0 && Pointcut1`::
- Picks out each join points that is picked out by both
- +
- Pointcut0
- +
- and
- +
- Pointcut1
- +
- .
+ Picks out each join points that is picked out by both `_Pointcut0_` and `_Pointcut1_` .
`Pointcut0 || Pointcut1`::
- Picks out each join point that is picked out by either pointcuts.
- +
- Pointcut0
- +
- or
- +
- Pointcut1
- +
- .
+ Picks out each join point that is picked out by either pointcuts. `_Pointcut0_` or `_Pointcut1_` .
`( Pointcut )`::
- Picks out each join points picked out by
- +
- Pointcut
- +
- .
+ Picks out each join points picked out by `_Pointcut_` .
==== Pointcut definition
Pointcuts are defined and named by the programmer with the `pointcut`
declaration.
+[source, java]
....
pointcut publicIntCall(int i):
call(public * *(int)) && args(i);
@@ -402,6 +251,7 @@ A named pointcut may be defined in either a class or aspect, and is
treated as a member of the class or aspect where it is found. As a
member, it may have an access modifier such as `public` or `private`.
+[source, java]
....
class C {
pointcut publicCall(int i):
@@ -418,6 +268,7 @@ Pointcuts that are not final may be declared abstract, and defined
without a body. Abstract pointcuts may only be declared within abstract
aspects.
+[source, java]
....
abstract aspect A {
abstract pointcut publicCall(int i);
@@ -426,6 +277,7 @@ abstract aspect A {
In such a case, an extending aspect may override the abstract pointcut.
+[source, java]
....
aspect B extends A {
pointcut publicCall(int i): call(public Foo.m(int)) && args(i);
@@ -444,6 +296,7 @@ is different than the scope of other members; the scope of other members
is the enclosing class _body_. This means that the following code is
legal:
+[source, java]
....
aspect B percflow(publicCall()) {
pointcut publicCall(): call(public Foo.m(int));
@@ -466,6 +319,7 @@ collection of types. The pointcut designators that allow this are
rather than a type does two things. First, it selects join points as
based on the type of the formal parameter. So the pointcut
+[source, java]
....
pointcut intArg(int i): args(i);
....
@@ -477,6 +331,7 @@ advice or pointcut.
Values can be exposed from named pointcuts as well, so
+[source, java]
....
pointcut publicCall(int x): call(public *.*(int)) && intArg(x);
pointcut intArg(int i): args(i);
@@ -489,6 +344,7 @@ There is one special case for this kind of exposure. Exposing an
argument of type Object will also match primitive typed arguments, and
expose a "boxed" version of the primitive. So,
+[source, java]
....
pointcut publicCall(): call(public *.*(..)) && args(Object);
....
@@ -496,6 +352,7 @@ pointcut publicCall(): call(public *.*(..)) && args(Object);
will pick out all unary methods that take, as their only argument,
subtypes of Object (i.e., not primitive types like `int`), but
+[source, java]
....
pointcut publicCall(Object o): call(public *.*(..)) && args(o);
....
@@ -507,6 +364,7 @@ argument was an `int`, then the value passed to advice will be of type
The "boxing" of the primitive value is based on the _original_ primitive
type. So in the following program
+[source, java]
....
public class InstanceOf {
@@ -569,6 +427,7 @@ field is being set to, so at a set join point, that value can be
accessed with an `args` pointcut. So an aspect guarding a static integer
variable x declared in type T might be written as
+[source, java]
....
aspect GuardedX {
static final int MAX_CHANGE = 100;
@@ -632,6 +491,7 @@ the exception being handled. That value can be accessed with an `args`
pointcut. So an aspect used to put `FooException` objects into some
normal form before they are handled could be written as
+[source, java]
....
aspect NormalizeFooException {
before(FooException e): handler(FooException) && args(e) {
@@ -650,6 +510,7 @@ of advice
This can be used, for example, to filter out any join point in the
control flow of advice from a particular aspect.
+[source, java]
....
aspect TraceStuff {
pointcut myAdvice(): adviceexecution() && within(TraceStuff);
@@ -719,6 +580,7 @@ Object). If it is the "*" wildcard, then any argument will match, and if
it is the special wildcard "..", then any number of arguments will
match, just like in signature patterns. So the pointcut
+[source, java]
....
args(int, .., String)
....
@@ -762,6 +624,7 @@ Anytime such state is accessed, it is accessed through the _most recent_
control flow that matched. So the "current arg" that would be printed by
the following program is zero, even though it is in many control flows.
+[source, java]
....
class Test {
public static void main(String[] args) {
@@ -842,6 +705,7 @@ false. Within this expression, the `thisJoinPoint` object is available.
So one (extremely inefficient) way of picking out all call join points
would be to use the pointcut
+[source, java]
....
if(thisJoinPoint.getKind().equals("call"))
....
@@ -922,6 +786,7 @@ while constructor declarations omit the return type and replace the
method name with the class name. The start of a particular method
declaration, in class `Test`, for example, might be
+[source, java]
....
class C {
public final void foo() throws ArrayOutOfBoundsException { ... }
@@ -931,12 +796,14 @@ class C {
In AspectJ, method signature patterns have all these, but most elements
can be replaced by wildcards. So
+[source, java]
....
call(public final void C.foo() throws ArrayOutOfBoundsException)
....
picks out call join points to that method, and the pointcut
+[source, java]
....
call(public final void *.*() throws ArrayOutOfBoundsException)
....
@@ -949,12 +816,14 @@ throw `ArrayOutOfBounds` exceptions.
The defining type name, if not present, defaults to *, so another way of
writing that pointcut would be
+[source, java]
....
call(public final void *() throws ArrayOutOfBoundsException)
....
The wildcard `..` indicates zero or more parameters, so
+[source, java]
....
execution(void m(..))
....
@@ -962,6 +831,7 @@ execution(void m(..))
picks out execution join points for void methods named `m`, of any
number of arguments, while
+[source, java]
....
execution(void m(.., int))
....
@@ -974,6 +844,7 @@ signature pattern should match methods without a particular modifier,
such as all non-public methods, the appropriate modifier should be
negated with the `!` operator. So,
+[source, java]
....
withincode(!public void foo())
....
@@ -981,6 +852,7 @@ withincode(!public void foo())
picks out all join points associated with code in null non-public void
methods named `foo`, while
+[source, java]
....
withincode(void foo())
....
@@ -991,12 +863,14 @@ named `foo`, regardless of access modifier.
Method names may contain the * wildcard, indicating any number of
characters in the method name. So
+[source, java]
....
call(int *())
....
picks out all call join points to `int` methods regardless of name, but
+[source, java]
....
call(int get*())
....
@@ -1009,6 +883,7 @@ than using a particular class name. So the execution join points of
private null constructor of a class C defined to throw an
ArithmeticException can be picked out with
+[source, java]
....
execution(private C.new() throws ArithmeticException)
....
@@ -1027,6 +902,7 @@ type used to access the method. A common mistake is to specify a
declaring type for the `call` pointcut that is a subtype of the
originally-declaring type. For example, given the class
+[source, java]
....
class Service implements Runnable {
public void run() { ... }
@@ -1035,12 +911,14 @@ class Service implements Runnable {
the following pointcut
+[source, java]
....
call(void Service.run())
....
would fail to pick out the join point for the code
+[source, java]
....
((Runnable) new Service()).run();
....
@@ -1049,6 +927,7 @@ Specifying the originally-declaring type is correct, but would pick out
any such call (here, calls to the `run()` method of any Runnable). In
this situation, consider instead picking out the target type:
+[source, java]
....
call(void run()) && target(Service)
....
@@ -1058,6 +937,7 @@ method signature specifies a declaring type, the pointcut will only
match methods declared in that type, or methods that override methods
declared in or inherited by that type. So the pointcut
+[source, java]
....
execution(public void Middle.*())
....
@@ -1068,6 +948,7 @@ Middle, even if those methods are overridden in a subclass of Middle. So
the pointcut would pick out the method-execution join point for Sub.m()
in this code:
+[source, java]
....
class Super {
protected void m() { ... }
@@ -1085,6 +966,7 @@ Type patterns may be used to pick out methods and constructors based on
their throws clauses. This allows the following two kinds of extremely
wildcarded pointcuts:
+[source, java]
....
pointcut throwsMathlike():
// each call to a method with a throws clause containing at least
@@ -1190,6 +1072,7 @@ So exact type patterns match based on usual Java scope rules.
There is a special type name, *, which is also a type pattern. * picks
out all types, including primitive types. So
+[source, java]
....
call(void foo(*))
....
@@ -1202,6 +1085,7 @@ patterns. The * wildcard matches zero or more characters characters
except for ".", so it can be used when types have a certain naming
convention. So
+[source, java]
....
handler(java.util.*Map)
....
@@ -1209,6 +1093,7 @@ handler(java.util.*Map)
picks out the types java.util.Map and java.util.java.util.HashMap, among
others, and
+[source, java]
....
handler(java.util.*)
....
@@ -1221,6 +1106,7 @@ The "`..`" wildcard matches any sequence of characters that start and
end with a ".", so it can be used to pick out all types in any
subpackage, or all inner types. So
+[source, java]
....
within(com.xerox..*)
....
@@ -1238,6 +1124,7 @@ It is possible to pick out all subtypes of a type (or a collection of
types) with the "+" wildcard. The "+" wildcard follows immediately a
type name pattern. So, while
+[source, java]
....
call(Foo.new())
....
@@ -1245,6 +1132,7 @@ call(Foo.new())
picks out all constructor call join points where an instance of exactly
type Foo is constructed,
+[source, java]
....
call(Foo+.new())
....
@@ -1252,6 +1140,7 @@ call(Foo+.new())
picks out all constructor call join points where an instance of any
subtype of Foo (including Foo itself) is constructed, and the unlikely
+[source, java]
....
call(*Handler+.new())
....
@@ -1271,6 +1160,7 @@ Type patterns are built up out of type name patterns, subtype patterns,
and array type patterns, and constructed with boolean operators `&&`,
`||`, and `!`. So
+[source, java]
....
staticinitialization(Foo || Bar)
....
@@ -1278,6 +1168,7 @@ staticinitialization(Foo || Bar)
picks out the static initializer execution join points of either Foo or
Bar, and
+[source, java]
....
call((Foo+ && ! Foo).new(..))
....
@@ -1289,6 +1180,7 @@ not Foo itself, is constructed.
Here is a summary of the pattern syntax used in AspectJ:
+[source, text]
....
MethodPattern =
[ModifiersPattern] TypePattern
@@ -1397,6 +1289,7 @@ interpretations of after advice: After the execution of a join point
completes normally, after it throws an exception, or after it does
either one. AspectJ allows after advice for any of these situations.
+[source, java]
....
aspect A {
pointcut publicCall(): call(public Object *(..));
@@ -1415,6 +1308,7 @@ aspect A {
After returning advice may not care about its returned object, in which
case it may be written
+[source, java]
....
after() returning: call(public Object *(..)) {
System.out.println("Returned normally");
@@ -1448,6 +1342,7 @@ must be declared with a return type, like a method.
Thus, a simple use of around advice is to make a particular method
constant:
+[source, java]
....
aspect A {
int around(): call(int C.foo()) {
@@ -1459,6 +1354,7 @@ aspect A {
Within the body of around advice, though, the computation of the
original join point can be executed with the special syntax
+[source, java]
....
proceed( ... )
....
@@ -1468,6 +1364,7 @@ pointcut, and returns whatever the around is declared to return. So the
following around advice will double the second argument to `foo`
whenever it is called, and then halve its result:
+[source, java]
....
aspect A {
int around(int i): call(int C.foo(Object, int)) && args(i) {
@@ -1483,6 +1380,7 @@ is originally a primitive value. And when the advice returns an Object
value, that value is converted back to whatever representation it was
originally. So another way to write the doubling and halving advice is:
+[source, java]
....
aspect A {
Object around(int i): call(int C.foo(Object, int)) && args(i) {
@@ -1500,6 +1398,7 @@ program the first call to proceed will be treated as a method call to
the `ICanProceed` instance, whereas the second call to proceed is
treated as the special proceed form.
+[source, java]
....
aspect A {
Object around(ICanProceed canProceed) : execution(* *(..)) && this(canProceed) {
@@ -1519,6 +1418,7 @@ method parameters. In particular, assigning to any parameter affects
only the value of the parameter, not the value that it came from. This
means that
+[source, java]
....
aspect A {
after() returning (int i): call(int C.foo()) {
@@ -1536,6 +1436,7 @@ less-precedent advice and the underlying join point by supplying
different values for the variables. For example, this aspect replaces
the string bound to `s` in the named pointcut `privateData`:
+[source, java]
....
aspect A {
Object around(String s): MyPointcuts.privateData(s) {
@@ -1551,6 +1452,7 @@ In the following aspect, the around advice replaces the declared target
`List` with an `ArrayList`. This is valid code at compile-time since the
types match.
+[source, java]
....
import java.util.*;
@@ -1565,6 +1467,7 @@ But imagine a simple program where the actual target is `LinkedList`. In
this case, the advice would cause a `ClassCastException` at runtime, and
`peek()` is not declared in `ArrayList`.
+[source, java]
....
public class Test {
public static void main(String[] args) {
@@ -1577,6 +1480,7 @@ The `ClassCastException` can occur even in situations where it appears
to be unnecessary, e.g., if the program is changed to call `size()`,
declared in `List`:
+[source, java]
....
public class Test {
public static void main(String[] args) {
@@ -1605,6 +1509,7 @@ signalled by the compiler.
For example, in the following declarations:
+[source, java]
....
import java.io.FileNotFoundException;
@@ -1626,22 +1531,14 @@ aspect A {
both pieces of advice are illegal. The first because the body throws an
undeclared checked exception, and the second because field get join
-points cannot throw `FileNotFoundException`s.
+points cannot throw ``FileNotFoundException``s.
The exceptions that each kind of join point in AspectJ may throw are:
method call and execution::
- the checked exceptions declared by the target method's
- +
- throws
- +
- clause.
+ the checked exceptions declared by the target method's `_throws_` clause.
constructor call and execution::
- the checked exceptions declared by the target constructor's
- +
- throws
- +
- clause.
+ the checked exceptions declared by the target constructor's `_throws_` clause.
field get and set::
no checked exceptions can be thrown from these join points.
exception handler execution::
@@ -1649,11 +1546,7 @@ exception handler execution::
static initializer execution::
no checked exceptions can be thrown from these join points.
pre-initialization and initialization::
- any exception that is in the throws clause of
- +
- all
- +
- constructors of the initialized class.
+ any exception that is in the throws clause of all constructors of the initialized class.
advice execution::
any exception that is in the throws clause of the advice.
@@ -1700,6 +1593,7 @@ precedence over the one that appears later.
These rules can lead to circularity, such as
+[source, java]
....
aspect A {
before(): execution(void main(String[] args)) {}
@@ -1747,6 +1641,7 @@ encapsulates some of the context of the advice's current or enclosing
join point. These variables exist because some pointcuts may pick out
very large collections of join points. For example, the pointcut
+[source, java]
....
pointcut publicCall(): call(public * *(..));
....
@@ -1843,6 +1738,7 @@ The effect of such a declaration is to make <OnType> support the new
method. Even if <OnType> is an interface. Even if the method is neither
public nor abstract. So the following is legal AspectJ code:
+[source, java]
....
interface Iface {}
@@ -1979,6 +1875,7 @@ Inter-type declarations raise the possibility of conflicts among locally
declared members and inter-type members. For example, assuming
`otherPackage` is not the package containing the aspect `A`, the code
+[source, java]
....
aspect A {
private Registry otherPackage.onType.r;
@@ -2001,6 +1898,7 @@ there is no conflict: The aspect cannot see such a field, and no code in
If `onType` defines a public field "`r`", there is a conflict: The
expression
+[source, java]
....
this.r = r
....
@@ -2071,6 +1969,7 @@ might define appropriate inter-type `void
fulfills the `Runnable` interface. In order to implement the methods in
the `Runnable` interface, the inter-type `run()` method must be public:
+[source, java]
....
aspect A {
declare parents: SomeClass implements Runnable;
@@ -2091,9 +1990,10 @@ initializers. The order of super-interface instantiation is observable.
We fix this order with the following properties: A supertype is
initialized before a subtype, initialized code runs only once, and the
initializers for a type's superclass are run before the initializers for
-its superinterfaces. Consider the following hierarchy where \{`Object`,
-`C`, `D`, `E`} are classes, \{`M`, `N`, `O`, `P`, `Q`} are interfaces.
+its superinterfaces. Consider the following hierarchy where {`Object`,
+`C`, `D`, `E`} are classes, {`M`, `N`, `O`, `P`, `Q`} are interfaces.
+[source, text]
....
Object M O
\ / \ /
@@ -2106,6 +2006,7 @@ its superinterfaces. Consider the following hierarchy where \{`Object`,
when a new `E` is instantiated, the initializers run in this order:
+[source, text]
....
Object M C O N D Q P E
....
@@ -2158,6 +2059,7 @@ Pointcut
For example, the aspect
+[source, java]
....
aspect A {
declare soft: Exception: execution(void main(String[] args));
@@ -2169,6 +2071,7 @@ Would, at the execution join point, catch any `Exception` and rethrow a
This is similar to what the following advice would do
+[source, java]
....
aspect A {
void around() execution(void main(String[] args)) {
@@ -2187,6 +2090,7 @@ Like advice, the declare soft form has no effect in an abstract aspect
that is not extended by a concreate aspect. So the following code will
not compile unless it is compiled with an extending concrete aspect:
+[source, java]
....
abstract aspect A {
abstract pointcut softeningPC();
@@ -2223,6 +2127,7 @@ of their name should have precedence over all other aspects, and (2) the
Logging aspect (and any aspect that extends it) should have precedence
over all non-security aspects, can be expressed by:
+[source, java]
....
declare precedence: *..*Security*, Logging+, *;
....
@@ -2235,6 +2140,7 @@ accomplished by stating that CountEntry has precedence over
DisallowNulls. This declaration could be in either aspect, or in
another, ordering aspect:
+[source, java]
....
aspect Ordering {
declare precedence: CountEntry, DisallowNulls;
@@ -2259,6 +2165,7 @@ aspect CountEntry {
It is an error for any aspect to be matched by more than one TypePattern
in a single decare precedence, so:
+[source, java]
....
declare precedence: A, B, A ; // error
....
@@ -2267,6 +2174,7 @@ However, multiple declare precedence forms may legally have this kind of
circularity. For example, each of these declare precedence is perfectly
legal:
+[source, java]
....
declare precedence: B, A;
declare precedence: A, B;
@@ -2280,6 +2188,7 @@ idiom that can be used to enforce that A and B are strongly independent.
Consider the following library aspects:
+[source, java]
....
abstract aspect Logging {
abstract pointcut logged();
@@ -2313,12 +2222,14 @@ aspects, say, MyLogging and MyProfiling. Because advice only applies
from concrete aspects, the declare precedence form only matters when
declaring precedence with concrete aspects. So
+[source, java]
....
declare precedence: Logging, Profiling;
....
has no effect, but both
+[source, java]
....
declare precedence: MyLogging, MyProfiling;
declare precedence: Logging+, Profiling+;
@@ -2526,6 +2437,7 @@ All advice runs in the context of an aspect instance, but it is possible
to write a piece of advice with a pointcut that picks out a join point
that must occur before asopect instantiation. For example:
+[source, java]
....
public class Client
{
@@ -2574,6 +2486,7 @@ private or protected resources of other types. To allow this, aspects
may be declared `privileged`. Code in priviliged aspects has access to
all members, even private ones.
+[source, java]
....
class C {
private int i = 0;
@@ -2594,6 +2507,7 @@ If a privileged aspect can access multiple versions of a particular
member, then those that it could see if it were not privileged take
precedence. For example, in the code
+[source, java]
....
class C {
private int i = 0;