aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB/semantics.xml
diff options
context:
space:
mode:
authorehilsdal <ehilsdal>2003-04-08 21:59:39 +0000
committerehilsdal <ehilsdal>2003-04-08 21:59:39 +0000
commite2af842ae7dbf3b0315a5f73d3d5ec9b7f041556 (patch)
treea4e993a588298b0d6babdf643de8d35991a2ebd6 /docs/progGuideDB/semantics.xml
parentf11709f8bc26a053ff573039cc0b5ee887c005ff (diff)
downloadaspectj-e2af842ae7dbf3b0315a5f73d3d5ec9b7f041556.tar.gz
aspectj-e2af842ae7dbf3b0315a5f73d3d5ec9b7f041556.zip
folded in material from README-11.html
finally totally and completely stomped out "introduction" minor formatting changes generating better filenames for the progguide added A4 version of quick reference
Diffstat (limited to 'docs/progGuideDB/semantics.xml')
-rw-r--r--docs/progGuideDB/semantics.xml1627
1 files changed, 951 insertions, 676 deletions
diff --git a/docs/progGuideDB/semantics.xml b/docs/progGuideDB/semantics.xml
index f137f7497..0bc896254 100644
--- a/docs/progGuideDB/semantics.xml
+++ b/docs/progGuideDB/semantics.xml
@@ -2,323 +2,300 @@
<title>Language Semantics</title>
- <para>
- AspectJ extends Java by overlaying a concept of join points onto the
- existing Java semantics and adding a few new program elements to Java:
- </para>
-
- <para>
- A join point is a well-defined point in the execution of a program. These
- include method and constructor calls, field accesses and others described
- below.
- </para>
-
- <para>
- A pointcut picks out join points, and exposes some of the values in the
- execution context of those join points. There are several primitive
- pointcut designators, and others can be named and defined by the
- <literal>pointcut</literal> declaration.
- </para>
-
- <para>
- A piece of advice is code that executes at each join point in a pointcut. Advice has
- access to the values exposed by the pointcut. Advice is defined by
- <literal>before</literal>, <literal>after</literal>, and
- <literal>around</literal> declarations.
- </para>
-
- <para>
- Inter-type declarations form AspectJ's static crosscutting features, that
- is, is code that may change the type structure of a program, by adding to
- or extending interfaces and classes with new fields, constructors, or
- methods. Some inter-type declarations are defined through an extension of
- usual method, field, and constructor declarations, and other declarations
- are made with a new <literal>declare</literal> keyword.
- </para>
-
- <para>
- An aspect is a crosscutting type that encapsulates pointcuts, advice, and
- static crosscutting features. By type, we mean Java's notion: a modular
- unit of code, with a well-defined interface, about which it is possible to
- do reasoning at compile time. Aspects are defined by the
- <literal>aspect</literal> declaration.
- </para>
-
- <sect1 id="joinPoints">
+ <sect1 id="semantics-intro">
+ <title>Introduction</title>
+
+ <para>
+ AspectJ extends Java by overlaying a concept of join points onto the
+ existing Java semantics and adding a few new program elements to Java:
+ </para>
+
+ <para>
+ A join point is a well-defined point in the execution of a
+ program. These include method and constructor calls, field accesses and
+ others described below.
+ </para>
+
+ <para>
+ A pointcut picks out join points, and exposes some of the values in the
+ execution context of those join points. There are several primitive
+ pointcut designators, and others can be named and defined by the
+ <literal>pointcut</literal> declaration.
+ </para>
+
+ <para>
+ A piece of advice is code that executes at each join point in a
+ pointcut. Advice has access to the values exposed by the
+ pointcut. Advice is defined by <literal>before</literal>,
+ <literal>after</literal>, and <literal>around</literal> declarations.
+ </para>
+
+ <para>
+ Inter-type declarations form AspectJ's static crosscutting features,
+ that is, is code that may change the type structure of a program, by
+ adding to or extending interfaces and classes with new fields,
+ constructors, or methods. Some inter-type declarations are defined
+ through an extension of usual method, field, and constructor
+ declarations, and other declarations are made with a new
+ <literal>declare</literal> keyword.
+ </para>
+
+ <para>
+ An aspect is a crosscutting type that encapsulates pointcuts, advice,
+ and static crosscutting features. By type, we mean Java's notion: a
+ modular unit of code, with a well-defined interface, about which it is
+ possible to do reasoning at compile time. Aspects are defined by the
+ <literal>aspect</literal> declaration.
+ </para>
+ </sect1>
+
+<!-- ============================== -->
+
+ <sect1 id="semantics-joinPoints">
<title>Join Points</title>
<para>
While aspects define types that crosscut, the AspectJ system does not
- allow completely arbitrary crosscutting. Rather, aspects define types that
- cut across principled points in a program's execution. These principled
- points are called join points.
+ allow completely arbitrary crosscutting. Rather, aspects define types
+ that cut across principled points in a program's execution. These
+ principled points are called join points.
</para>
-
<para>
- A join point is a well-defined point in the execution of a program. The
- join points defined by AspectJ are:
+ A join point is a well-defined point in the execution of a
+ program. The join points defined by AspectJ are:
</para>
<variablelist>
-
<varlistentry>
<term>Method call</term>
<listitem>
- <para>
- When a method is called, not including super calls of non-static
- methods.
- </para>
+ When a method is called, not including super calls of
+ non-static methods.
</listitem>
</varlistentry>
<varlistentry>
<term>Method execution</term>
<listitem>
- <para>
- When the body of code for an actual method executes.
- </para>
+ When the body of code for an actual method executes.
</listitem>
</varlistentry>
-
<varlistentry>
<term>Constructor call</term>
<listitem>
- <para>
- When an object is built and that object's initial constructor is
- called (i.e., not for "super" or "this" constructor calls). The
- object being constructed is returned at a constructor call join
- point, so its return type is considered to be the type of the
- object, and the object itself may be accessed with <literal>after
- returning</literal> advice.
- </para>
+ When an object is built and that object's initial constructor is
+ called (i.e., not for "super" or "this" constructor calls). The
+ object being constructed is returned at a constructor call join
+ point, so its return type is considered to be the type of the
+ object, and the object itself may be accessed with <literal>after
+ returning</literal> advice.
</listitem>
</varlistentry>
<varlistentry>
<term>Constructor execution</term>
<listitem>
- <para>
- 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
- <literal>this</literal> pointcut. No value is returned from
- a constructor execution join point, so its return type is
- considered to be void.
- </para>
+ 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 <literal>this</literal> 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.
</listitem>
</varlistentry>
<varlistentry>
<term>Static initializer execution</term>
<listitem>
- <para>
- When the static initializer for a class executes.
- No value is returned from a static initializer execution join
- point, so its return type is considered to be void.
- </para>
+ When the static initializer for a class executes. No value is
+ returned from a static initializer execution join point, so its
+ return type is considered to be void.
</listitem>
</varlistentry>
<varlistentry>
<term>Object pre-initialization</term>
<listitem>
- <para>
- Before the object initialization code for a particular class runs.
- 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 <literal>this()</literal> and
- <literal>super()</literal> constructor calls.
- No value is returned from an object pre-initialization join
- point, so its return type is considered to be void.
- </para>
+ Before the object initialization code for a particular class runs.
+ 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 <literal>this()</literal> and
+ <literal>super()</literal> constructor calls. No value is
+ returned from an object pre-initialization join point, so its
+ return type is considered to be void.
</listitem>
</varlistentry>
<varlistentry>
<term>Object initialization</term>
<listitem>
- <para>
- When the object initialization code for a particular class runs.
- This encompasses the time between the return of its parent's
- constructor 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
- <literal>this</literal> pointcut.
- No value is returned from a constructor execution join point, so
- its return type is considered to be void.
- </para>
+ When the object initialization code for a particular class runs.
+ This encompasses the time between the return of its parent's
+ constructor 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
+ <literal>this</literal> pointcut. No value is returned from a
+ constructor execution join point, so its return type is
+ considered to be void.
</listitem>
</varlistentry>
<varlistentry>
<term>Field reference</term>
<listitem>
- <para>
- When a non-constant field is referenced.
- [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.]
- </para>
+ When a non-constant field is referenced. [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.]
</listitem>
</varlistentry>
<varlistentry>
<term>Field set</term>
<listitem>
- <para>
- When a field is assigned to.
- Field set join points are considered to have one argument,
- the value the field is being set to.
- No value is returned from a field set join point, so
- its return type is considered to be void.
- [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.]
- </para>
+ When a field is assigned to.
+ Field set join points are considered to have one argument,
+ the value the field is being set to.
+ No value is returned from a field set join point, so
+ its return type is considered to be void.
+ [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.]
</listitem>
</varlistentry>
<varlistentry>
<term>Handler execution</term>
<listitem>
- <para>
- When an exception handler executes.
- Handler execution join points are considered to have one argument,
- the exception being handled.
- No value is returned from a field set join point, so
- its return type is considered to be void.
- </para>
+ When an exception handler executes.
+ Handler execution join points are considered to have one argument,
+ the exception being handled.
+ No value is returned from a field set join point, so
+ its return type is considered to be void.
</listitem>
</varlistentry>
<varlistentry>
<term>Advice execution</term>
<listitem>
- <para>
- When the body of code for a piece of advice executes.
- </para>
+ When the body of code for a piece of advice executes.
</listitem>
</varlistentry>
</variablelist>
-
-
-
-
</sect1>
<!-- ============================== -->
- <sect1 id="pointcuts">
+ <sect1 id="semantics-pointcuts">
<title>Pointcuts</title>
<para>
- A pointcut is a program element that picks out join points and exposes
- data from the execution context of those join points. Pointcuts are used
- primarily by advice. They can be composed with boolean operators to
- build up other pointcuts. The primitive pointcuts and combinators
- provided by the language are:
+ A pointcut is a program element that picks out join points and
+ exposes data from the execution context of those join points.
+ Pointcuts are used primarily by advice. They can be composed with
+ boolean operators to build up other pointcuts. The primitive
+ pointcuts and combinators provided by the language are:
</para>
<variablelist>
-
<varlistentry>
<term><literal>call(<replaceable>MethodPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each method call join point whose signature matches
- <replaceable>MethodPattern</replaceable>. </para>
+ Picks out each method call join point whose signature matches
+ <replaceable>MethodPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>execution(<replaceable>MethodPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each method execution join point whose signature matches
- <replaceable>MethodPattern</replaceable>. </para>
+ Picks out each method execution join point whose signature matches
+ <replaceable>MethodPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>get(<replaceable>FieldPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each field reference join point whose signature matches
+ Picks out each field reference join point whose signature matches
<replaceable>FieldPattern</replaceable>.
[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.] </para>
+ join points, since Java requires them to be inlined.]
</listitem>
</varlistentry>
<varlistentry>
<term><literal>set(<replaceable>FieldPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each field set join point whose signature matches
+ Picks out each field set join point whose signature matches
<replaceable>FieldPattern</replaceable>.
[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.]</para>
+ references to be inlined.]
</listitem>
</varlistentry>
-
<varlistentry>
<term><literal>call(<replaceable>ConstructorPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each constructor call join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>. </para>
+ Picks out each constructor call join point whose signature matches
+ <replaceable>ConstructorPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>execution(<replaceable>ConstructorPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each constructor execution join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>. </para>
+ Picks out each constructor execution join point whose signature matches
+ <replaceable>ConstructorPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>initialization(<replaceable>ConstructorPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each object initialization join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>. </para>
+ Picks out each object initialization join point whose signature matches
+ <replaceable>ConstructorPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>preinitialization(<replaceable>ConstructorPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each object pre-initialization join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>. </para>
+ Picks out each object pre-initialization join point whose signature matches
+ <replaceable>ConstructorPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>staticinitialization(<replaceable>TypePattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each static initializer execution join point whose signature matches
- <replaceable>TypePattern</replaceable>. </para>
+ Picks out each static initializer execution join point whose signature matches
+ <replaceable>TypePattern</replaceable>.
</listitem>
</varlistentry>
-
<varlistentry>
<term><literal>handler(<replaceable>TypePattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each exception handler join point whose signature matches
- <replaceable>TypePattern</replaceable>. </para>
+ Picks out each exception handler join point whose signature matches
+ <replaceable>TypePattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>adviceexecution()</literal></term>
<listitem>
- <para>Picks out all advice execution join points.</para>
+ Picks out all advice execution join points.
</listitem>
</varlistentry>
@@ -326,151 +303,147 @@
<varlistentry>
<term><literal>within(<replaceable>TypePattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the executing code is defined
- in a type matched by <replaceable>TypePattern</replaceable>. </para>
+ Picks out each join point where the executing code is defined
+ in a type matched by <replaceable>TypePattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>withincode(<replaceable>MethodPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the executing code is defined
- in a method whose signature matches
- <replaceable>MethodPattern</replaceable>. </para>
+ Picks out each join point where the executing code is defined in
+ a method whose signature matches
+ <replaceable>MethodPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>withincode(<replaceable>ConstructorPattern</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the executing code is defined
+ Picks out each join point where the executing code is defined
in a constructor whose signature matches
- <replaceable>ConstructorPattern</replaceable>. </para>
+ <replaceable>ConstructorPattern</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>cflow(<replaceable>Pointcut</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point in the control flow of any join point
+ Picks out each join point in the control flow of any join point
<replaceable>P</replaceable> picked out by
<replaceable>Pointcut</replaceable>, including
- <replaceable>P</replaceable> itself.</para>
+ <replaceable>P</replaceable> itself.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>cflowbelow(<replaceable>Pointcut</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point in the control flow of any join point
+ Picks out each join point in the control flow of any join point
<replaceable>P</replaceable> picked out by
<replaceable>Pointcut</replaceable>, but not
- <replaceable>P</replaceable> itself.</para>
+ <replaceable>P</replaceable> itself.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>this(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the currently executing object
+ Picks out each join point where the currently executing object
(the object bound to <literal>this</literal>) is an instance of
<replaceable>Type</replaceable>, or of the type of
<replaceable>Id</replaceable> (which must be bound in the enclosing
advice or pointcut definition).
Will not match any join points from static contexts.
- </para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>target(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the target object (the object
+ 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
<replaceable>Type</replaceable>, or of the type of
<replaceable>Id</replaceable> (which must be bound in the enclosing
advice or pointcut definition).
Will not match any calls, gets, or sets of static members.
- </para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>args(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>, ...)</literal></term>
<listitem>
- <para>Picks out each join point where the arguments are instances of
- a type of the appropriate type pattern or identifier. </para>
+ Picks out each join point where the arguments are instances of
+ a type of the appropriate type pattern or identifier.
</listitem>
</varlistentry>
<varlistentry>
<term><literal><replaceable>PointcutId</replaceable>(<replaceable>TypePattern</replaceable> or <replaceable>Id</replaceable>, ...)</literal></term>
<listitem>
- <para>Picks out each join point that is picked out by the
+ Picks out each join point that is picked out by the
user-defined pointcut designator named by
- <replaceable>PointcutId</replaceable>. </para>
+ <replaceable>PointcutId</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>if(<replaceable>BooleanExpression</replaceable>)</literal></term>
<listitem>
- <para>Picks out each join point where the boolean expression
+ Picks out each join point where the boolean expression
evaluates to <literal>true</literal>. The boolean expression used
can only access static members, variables exposed by teh enclosing
pointcut or advice, and <literal>thisJoinPoint</literal> forms. In
- particular, it cannot call non-static methods on the aspect. </para>
+ particular, it cannot call non-static methods on the aspect.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>! <replaceable>Pointcut</replaceable></literal></term>
<listitem>
- <para>Picks out each join point that is not picked out by
- <replaceable>Pointcut</replaceable>. </para>
+ Picks out each join point that is not picked out by
+ <replaceable>Pointcut</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal><replaceable>Pointcut0</replaceable> <![CDATA[&&]]> <replaceable>Pointcut1</replaceable></literal></term>
<listitem>
- <para>Picks out each join points that is picked out by both
+ Picks out each join points that is picked out by both
<replaceable>Pointcut0</replaceable> and
- <replaceable>Pointcut1</replaceable>. </para>
+ <replaceable>Pointcut1</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal><replaceable>Pointcut0</replaceable> || <replaceable>Pointcut1</replaceable></literal></term>
<listitem>
- <para>Picks out each join point that is picked out by either
+ Picks out each join point that is picked out by either
pointcuts. <replaceable>Pointcut0</replaceable> or
- <replaceable>Pointcut1</replaceable>. </para>
+ <replaceable>Pointcut1</replaceable>.
</listitem>
</varlistentry>
<varlistentry>
<term><literal>( <replaceable>Pointcut</replaceable> )</literal></term>
<listitem>
- <para>(parentheses) Picks out each join points picked out by
- <replaceable>Pointcut</replaceable>. </para>
+ Picks out each join points picked out by
+ <replaceable>Pointcut</replaceable>.
</listitem>
</varlistentry>
</variablelist>
<sect2>
- <title>Pointcut naming
- </title>
+ <title>Pointcut definition</title>
<para>
- A named pointcut is defined with the <literal>pointcut</literal>
- declaration.
+ Pointcuts are defined and named by the programmer with the
+ <literal>pointcut</literal> declaration.
</para>
-
<programlisting>
-pointcut publicIntCall(int i):
- call(public * *(int)) <![CDATA[&&]]> args(i);
+ pointcut publicIntCall(int i):
+ call(public * *(int)) <![CDATA[&&]]> args(i);
</programlisting>
<para>
@@ -481,15 +454,15 @@ pointcut publicIntCall(int i):
</para>
<programlisting>
-class C {
- pointcut publicCall(int i):
- call(public * *(int)) <![CDATA[&&]]> args(i);
-}
-
-class D {
- pointcut myPublicCall(int i):
- C.publicCall(i) <![CDATA[&&]]> within(SomeType);
-}
+ class C {
+ pointcut publicCall(int i):
+ call(public * *(int)) <![CDATA[&&]]> args(i);
+ }
+
+ class D {
+ pointcut myPublicCall(int i):
+ C.publicCall(i) <![CDATA[&&]]> within(SomeType);
+ }
</programlisting>
<para>
@@ -499,9 +472,9 @@ class D {
</para>
<programlisting>
-abstract aspect A {
- abstract pointcut publicCall(int i);
-}
+ abstract aspect A {
+ abstract pointcut publicCall(int i);
+ }
</programlisting>
<para>
@@ -510,67 +483,69 @@ abstract aspect A {
</para>
<programlisting>
-aspect B extends A {
- pointcut publicCall(int i): call(public Foo.m(int)) <![CDATA[&&]]> args(i);
-}
+ aspect B extends A {
+ pointcut publicCall(int i): call(public Foo.m(int)) <![CDATA[&&]]> args(i);
+ }
</programlisting>
- <para>For completeness, a pointcut with a declaration may be declared
- <literal>final</literal>. </para>
+ <para>
+ For completeness, a pointcut with a declaration may be declared
+ <literal>final</literal>.
+ </para>
<para>
Though named pointcut declarations appear somewhat like method
declarations, and can be overridden in subaspects, they cannot be
- overloaded. It is an error for two pointcuts to be named with the same
- name in the same class or aspect declaration.
+ overloaded. It is an error for two pointcuts to be named with the
+ same name in the same class or aspect declaration.
</para>
<para>
- The scope of a named pointcut is the enclosing class declaration. This
- is different than the scope of other members; the scope of other
- members is the enclosing class <emphasis>body</emphasis>. This means
- that the following code is legal:
+ The scope of a named pointcut is the enclosing class declaration.
+ This is different than the scope of other members; the scope of
+ other members is the enclosing class <emphasis>body</emphasis>.
+ This means that the following code is legal:
</para>
<programlisting>
-aspect B percflow(publicCall()) {
- pointcut publicCall(): call(public Foo.m(int));
-}
+ aspect B percflow(publicCall()) {
+ pointcut publicCall(): call(public Foo.m(int));
+ }
</programlisting>
-
</sect2>
<sect2>
<title>Context exposure</title>
<para>
- Pointcuts have an interface; they expose some parts of the execution
- context of the join points they pick out. For example, the PublicIntCall
- above exposes the first argument from the receptions of all public
- unary integer methods. This context is exposed by providing typed
- formal parameters to named pointcuts and advice, like the formal
- parameters of a Java method. These formal parameters are bound by name
- matching.
+ Pointcuts have an interface; they expose some parts of the
+ execution context of the join points they pick out. For example,
+ the PublicIntCall above exposes the first argument from the
+ receptions of all public unary integer methods. This context is
+ exposed by providing typed formal parameters to named pointcuts and
+ advice, like the formal parameters of a Java method. These formal
+ parameters are bound by name matching.
</para>
<para>
- On the right-hand side of advice or pointcut declarations, in certain
- pointcut designators, a Java identifier is allowed in place of a type
- or collection of types. The pointcut designators that allow this are
- <literal>this</literal>, <literal>target</literal>, and
- <literal>args</literal>. In all such cases, using an identifier rather
- than a type does two things. First, it selects join points as based on
- the type of the formal parameter. So the pointcut
+ On the right-hand side of advice or pointcut declarations, in
+ certain pointcut designators, a Java identifier is allowed in place
+ of a type or collection of types. The pointcut designators that
+ allow this are <literal>this</literal>, <literal>target</literal>,
+ and <literal>args</literal>. In all such cases, using an
+ identifier rather than a type does two things. First, it selects
+ join points as based on the type of the formal parameter. So the
+ pointcut
</para>
<programlisting>
-pointcut intArg(int i): args(i);
+ pointcut intArg(int i): args(i);
</programlisting>
<para>
- picks out join points where an <literal>int</literal> is being passed
- as an argument. Second, though, it makes the value of that argument
- available to the enclosing advice or pointcut.
+ picks out join points where an <literal>int</literal> is being
+ passed as an argument. Second, though, it makes the value of that
+ argument available to the enclosing advice or pointcut.
</para>
<para>
@@ -578,23 +553,23 @@ pointcut intArg(int i): args(i);
</para>
<programlisting>
-pointcut publicCall(int x): call(public *.*(int)) <![CDATA[&&]]> intArg(x);
-pointcut intArg(int i): args(i);
+ pointcut publicCall(int x): call(public *.*(int)) <![CDATA[&&]]> intArg(x);
+ pointcut intArg(int i): args(i);
</programlisting>
<para>
- is a legal way to pick out all calls to public methods accepting an int
- argument, and exposing that argument.
+ is a legal way to pick out all calls to public methods accepting an
+ int argument, and exposing that argument.
</para>
<para>
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,
+ argument of type Object will also match primitive typed arguments,
+ and expose a "boxed" version of the primitive. So,
</para>
<programlisting>
-pointcut publicCall(): call(public *.*(..)) <![CDATA[&&]]> args(Object);
+ pointcut publicCall(): call(public *.*(..)) <![CDATA[&&]]> args(Object);
</programlisting>
<para>
@@ -604,20 +579,21 @@ pointcut publicCall(): call(public *.*(..)) <![CDATA[&&]]> args(Object);
</para>
<programlisting>
-pointcut publicCall(Object o): call(public *.*(..)) <![CDATA[&&]]> args(o);
+ pointcut publicCall(Object o): call(public *.*(..)) <![CDATA[&&]]> args(o);
</programlisting>
<para>
- will pick out all unary methods that take any argument: And if the
- argument was an <literal>int</literal>, then the value passed to advice
- will be of type <literal>java.lang.Integer</literal>.
+ will pick out all unary methods that take any argument: And if the
+ argument was an <literal>int</literal>, then the value passed to
+ advice will be of type <literal>java.lang.Integer</literal>.
</para>
</sect2>
<sect2>
<title>Primitive pointcuts</title>
- <bridgehead>Method-related pointcuts</bridgehead>
+ <sect3>
+ <title>Method-related pointcuts</title>
<para>AspectJ provides two primitive pointcut designators designed to
capture method call and execution join points. </para>
@@ -626,8 +602,10 @@ pointcut publicCall(Object o): call(public *.*(..)) <![CDATA[&&]]> args(o);
<listitem><literal>call(<replaceable>MethodPattern</replaceable>)</literal></listitem>
<listitem><literal>execution(<replaceable>MethodPattern</replaceable>)</literal></listitem>
</itemizedlist>
+ </sect3>
- <bridgehead>Field-related pointcuts</bridgehead>
+ <sect3>
+ <title>Field-related pointcuts</title>
<para>
AspectJ provides two primitive pointcut designators designed to
@@ -647,15 +625,19 @@ pointcut publicCall(Object o): call(public *.*(..)) <![CDATA[&&]]> args(o);
</para>
<programlisting><![CDATA[
-aspect GuardedX {
- static final int MAX_CHANGE = 100;
- before(int newval): set(int T.x) && args(newval) {
- if (Math.abs(newval - T.x) > MAX_CHANGE)
- throw new RuntimeException();
- }
-}]]></programlisting>
+ aspect GuardedX {
+ static final int MAX_CHANGE = 100;
+ before(int newval): set(int T.x) && args(newval) {
+ if (Math.abs(newval - T.x) > MAX_CHANGE)
+ throw new RuntimeException();
+ }
+ }
+]]></programlisting>
- <bridgehead>Object creation-related pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Object creation-related pointcuts</title>
<para>
AspectJ provides primitive pointcut designators designed to
@@ -663,13 +645,16 @@ aspect GuardedX {
</para>
<itemizedlist>
- <listitem><literal>call(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>execution(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>initialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>preinitialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
+ <listitem><literal>call(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
+ <listitem><literal>execution(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
+ <listitem><literal>initialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
+ <listitem><literal>preinitialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
</itemizedlist>
- <bridgehead>Class initialization-related pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Class initialization-related pointcuts</title>
<para>
AspectJ provides one primitive pointcut designator to pick out
@@ -680,7 +665,10 @@ aspect GuardedX {
<listitem><literal>staticinitialization(<replaceable>TypePattern</replaceable>)</literal></listitem>
</itemizedlist>
- <bridgehead>Exception handler execution-related pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Exception handler execution-related pointcuts</title>
<para>
AspectJ provides one primitive pointcut designator to capture
@@ -700,14 +688,17 @@ aspect GuardedX {
</para>
<programlisting>
-aspect NormalizeFooException {
- before(FooException e): handler(FooException) <![CDATA[&&]]> args(e) {
- e.normalize();
- }
-}
+ aspect NormalizeFooException {
+ before(FooException e): handler(FooException) <![CDATA[&&]]> args(e) {
+ e.normalize();
+ }
+ }
</programlisting>
- <bridgehead>Advice execution-related pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Advice execution-related pointcuts</title>
<para>
AspectJ provides one primitive pointcut designator to capture
@@ -715,7 +706,7 @@ aspect NormalizeFooException {
</para>
<itemizedlist>
- <listitem><literal>adviceexecution()</literal></listitem>
+ <listitem><literal>adviceexecution()</literal></listitem>
</itemizedlist>
<para>
@@ -724,16 +715,19 @@ aspect NormalizeFooException {
</para>
<programlisting>
-aspect TraceStuff {
- pointcut myAdvice(): adviceexecution() <![CDATA[&&]]> within(TraceStuff);
+ aspect TraceStuff {
+ pointcut myAdvice(): adviceexecution() <![CDATA[&&]]> within(TraceStuff);
- before(): call(* *(..)) <![CDATA[&&]]> !cflow(myAdvice) {
- // do something
- }
-}
+ before(): call(* *(..)) <![CDATA[&&]]> !cflow(myAdvice) {
+ // do something
+ }
+ }
</programlisting>
- <bridgehead>State-based pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>State-based pointcuts</title>
<para>
Many concerns cut across the dynamic times when an object of a
@@ -760,7 +754,7 @@ aspect TraceStuff {
current join point is transfering control to. This means that the
target object is the same as the current object at a method execution
join point, for example, but may be different at a method call join
- point.
+ point.
</para>
<itemizedlist>
@@ -782,7 +776,7 @@ aspect TraceStuff {
</para>
<programlisting>
-args(int, .., String)
+ args(int, .., String)
</programlisting>
<para>
@@ -790,8 +784,10 @@ args(int, .., String)
<literal>int</literal> and the last is a <literal>String</literal>.
</para>
+ </sect3>
- <bridgehead>Control flow-based pointcuts</bridgehead>
+ <sect3>
+ <title>Control flow-based pointcuts</title>
<para>
Some concerns cut across the control flow of the program. The
@@ -824,7 +820,10 @@ args(int, .., String)
picked out by <replaceable>Pointcut</replaceable>.
</para>
- <bridgehead>Program text-based pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Program text-based pointcuts</title>
<para>
While many concerns cut across the runtime structure of the program,
@@ -860,7 +859,10 @@ args(int, .., String)
with code in a method or constructor's local or anonymous types.
</para>
- <bridgehead>Dynamic property-based pointcuts</bridgehead>
+ </sect3>
+
+ <sect3>
+ <title>Expression-based pointcuts</title>
<itemizedlist>
<listitem><literal>if(<replaceable>BooleanExpression</replaceable>)</literal></listitem>
@@ -876,9 +878,10 @@ args(int, .., String)
</para>
<programlisting>
-if(thisJoinPoint.getKind().equals("call"))
+ if(thisJoinPoint.getKind().equals("call"))
</programlisting>
+ </sect3>
</sect2>
<sect2>
@@ -890,77 +893,88 @@ if(thisJoinPoint.getKind().equals("call"))
join points.
</para>
- <bridgehead>Methods</bridgehead>
+ <sect3>
+ <title>Methods</title>
- <para>
- Join points associated with methods typically have method signatures,
- consisting of a method name, parameter types, return type, the types of
- the declared (checked) exceptions, and some type that the method could
- be called on (below called the "qualifying type").
- </para>
+ <para>
+ Join points associated with methods typically have method signatures,
+ consisting of a method name, parameter types, return type, the types of
+ the declared (checked) exceptions, and some type that the method could
+ be called on (below called the "qualifying type").
+ </para>
- <para>
- At a method call join point, the signature is a method signature whose
- qualifying type is the static type used to <emphasis>access</emphasis>
- the method. This means that the signature for the join point created
- from the call <literal>((Integer)i).toString()</literal> is different
- than that for the call <literal>((Object)i).toString()</literal>, even
- if <literal>i</literal> is the same variable.
- </para>
+ <para>
+ At a method call join point, the signature is a method signature whose
+ qualifying type is the static type used to <emphasis>access</emphasis>
+ the method. This means that the signature for the join point created
+ from the call <literal>((Integer)i).toString()</literal> is different
+ than that for the call <literal>((Object)i).toString()</literal>, even
+ if <literal>i</literal> is the same variable.
+ </para>
- <para>
- At a method execution join point, the signature a method signature
- whose qualifying type is the declaring type of the method.
- </para>
+ <para>
+ At a method execution join point, the signature a method signature
+ whose qualifying type is the declaring type of the method.
+ </para>
- <bridgehead>Fields</bridgehead>
+ </sect3>
- <para>
- Join points associated with fields typically have field signatures,
- consisting of a field name and a field type. A field reference join
- point has such a signature, and no parameters. A field set join point
- has such a signature, but has a has a single parameter whose type is
- the same as the field type.
- </para>
+ <sect3>
+ <title>Fields</title>
- <bridgehead>Constructors</bridgehead>
+ <para>
+ Join points associated with fields typically have field signatures,
+ consisting of a field name and a field type. A field reference join
+ point has such a signature, and no parameters. A field set join point
+ has such a signature, but has a has a single parameter whose type is
+ the same as the field type.
+ </para>
- <para>
- Join points associated with constructors typically have constructor
- signatures, consisting of a parameter types, the types of the declared
- (checked) exceptions, and the declaring type.
- </para>
+ </sect3>
- <para>
- At a constructor call join point, the signature is the constructor
- signature of the called constructor. At a constructor execution join
- point, the signature is the constructor signature of the currently
- executing constructor.
- </para>
+ <sect3>
+ <title>Constructors</title>
- <para>
- At object initialization and pre-initialization join points, the
- signature is the constructor signature for the constructor that started
- this initialization: the first constructor entered during this type's
- initialization of this object.
- </para>
+ <para>
+ Join points associated with constructors typically have constructor
+ signatures, consisting of a parameter types, the types of the declared
+ (checked) exceptions, and the declaring type.
+ </para>
- <bridgehead>Others</bridgehead>
+ <para>
+ At a constructor call join point, the signature is the constructor
+ signature of the called constructor. At a constructor execution join
+ point, the signature is the constructor signature of the currently
+ executing constructor.
+ </para>
- <para>
- At a handler execution join point, the signature is composed of the
- exception type that the handler handles.
- </para>
+ <para>
+ At object initialization and pre-initialization join points, the
+ signature is the constructor signature for the constructor that started
+ this initialization: the first constructor entered during this type's
+ initialization of this object.
+ </para>
+ </sect3>
- <para>
- At an advice execution join point, the signature is composed of the
- aspect type, the parameter types of the advice, the return type (void
- for all but around advice) and the types of the declared (checked)
- exceptions.
- </para>
+ <sect3>
+ <title>Others</title>
+ <para>
+ At a handler execution join point, the signature is composed of the
+ exception type that the handler handles.
+ </para>
+
+ <para>
+ At an advice execution join point, the signature is composed of the
+ aspect type, the parameter types of the advice, the return type (void
+ for all but around advice) and the types of the declared (checked)
+ exceptions.
+ </para>
+ </sect3>
</sect2>
+<!-- ============================== -->
+
<sect2>
<title>Matching</title>
@@ -985,9 +999,9 @@ if(thisJoinPoint.getKind().equals("call"))
<programlisting>
-class C {
- public final void foo() throws ArrayOutOfBoundsException { ... }
-}
+ class C {
+ public final void foo() throws ArrayOutOfBoundsException { ... }
+ }
</programlisting>
<para>
@@ -997,7 +1011,7 @@ class C {
<programlisting>
-call(public final void C.foo() throws ArrayOutOfBoundsException)
+ call(public final void C.foo() throws ArrayOutOfBoundsException)
</programlisting>
<para>
@@ -1005,7 +1019,7 @@ call(public final void C.foo() throws ArrayOutOfBoundsException)
</para>
<programlisting>
-call(public final void *.*() throws ArrayOutOfBoundsException)
+ call(public final void *.*() throws ArrayOutOfBoundsException)
</programlisting>
@@ -1023,7 +1037,7 @@ call(public final void *.*() throws ArrayOutOfBoundsException)
</para>
<programlisting>
-call(public final void *() throws ArrayOutOfBoundsException)
+ call(public final void *() throws ArrayOutOfBoundsException)
</programlisting>
<para>
@@ -1032,7 +1046,7 @@ call(public final void *() throws ArrayOutOfBoundsException)
</para>
<programlisting>
-execution(void m(..))
+ execution(void m(..))
</programlisting>
<para>
@@ -1041,10 +1055,9 @@ execution(void m(..))
</para>
<programlisting>
-execution(void m(.., int))
+ execution(void m(.., int))
</programlisting>
-
<para>
picks out execution join points for void methods named
<literal>m</literal> whose last parameter is of type
@@ -1059,7 +1072,7 @@ execution(void m(.., int))
</para>
<programlisting>
-withincode(!public void foo())
+ withincode(!public void foo())
</programlisting>
<para>
@@ -1068,7 +1081,7 @@ withincode(!public void foo())
</para>
<programlisting>
-withincode(void foo())
+ withincode(void foo())
</programlisting>
<para>
@@ -1082,7 +1095,7 @@ withincode(void foo())
</para>
<programlisting>
-call(int *())
+ call(int *())
</programlisting>
<para>
@@ -1091,7 +1104,7 @@ call(int *())
</para>
<programlisting>
-call(int get*())
+ call(int get*())
</programlisting>
<para>
@@ -1107,8 +1120,93 @@ call(int get*())
</para>
<programlisting>
-execution(private C.new() throws ArithmeticException)
+ execution(private C.new() throws ArithmeticException)
</programlisting>
+
+ <sect3>
+ <title>Matching based on the throws clause</title>
+
+ <para>
+ 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:
+ </para>
+
+<programlisting>
+ pointcut throwsMathlike():
+ // each call to a method with a throws clause containing at least
+ // one exception exception with "Math" in its name.
+ call(* *(..) throws *..*Math*);
+
+ pointcut doesNotThrowMathlike():
+ // each call to a method with a throws clause containing no
+ // exceptions with "Math" in its name.
+ call(* *(..) throws !*..*Math*);
+</programlisting>
+
+ <para>
+ A <replaceable>ThrowsClausePattern</replaceable> is a comma-separated list of
+ <replaceable>ThrowsClausePatternItem</replaceable>s, where
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable>ThrowsClausePatternItem</replaceable> :</term>
+ <listitem>
+ <literal>[ ! ]
+ <replaceable>TypeNamePattern</replaceable></literal>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ A <replaceable>ThrowsClausePattern</replaceable> matches the
+ throws clause of any code member signature. To match, each
+ <literal>ThrowsClausePatternItem</literal> must
+ match the throws clause of the member in question. If any item
+ doesn't match, then the whole pattern doesn't match.
+ </para>
+
+ <para>
+ If a ThrowsClausePatternItem begins with "!", then it matches a
+ particular throws clause if and only if <emphasis>none</emphasis>
+ of the types named in the throws clause is matched by the
+ <literal>TypeNamePattern</literal>.
+ </para>
+
+ <para>
+ If a <replaceable>ThrowsClausePatternItem</replaceable> does not
+ begin with "!", then it matches a throws clause if and only if
+ <emphasis>any</emphasis> of the types named in the throws clause
+ is matched by the <emphasis>TypeNamePattern</emphasis>.
+ </para>
+
+ <para>
+ The rule for "!" matching has one potentially surprising
+ property, in that these two pointcuts
+
+ <itemizedlist>
+ <listitem> call(* *(..) throws !IOException) </listitem>
+ <listitem> call(* *(..) throws (!IOException)) </listitem>
+ </itemizedlist>
+
+ will match differently on calls to
+
+ <blockquote>
+ <literal>
+ void m() throws RuntimeException, IOException {}
+ </literal>
+ </blockquote>
+ </para>
+
+ <para>
+ [1] will NOT match the method m(), because method m's throws
+ clause declares that it throws IOException. [2] WILL match the
+ method m(), because method m's throws clause declares the it
+ throws some exception which does not match IOException,
+ i.e. RuntimeException.
+ </para>
+ </sect3>
</sect2>
<sect2>
@@ -1120,164 +1218,200 @@ execution(private C.new() throws ArithmeticException)
using type patterns are simple.
</para>
- <bridgehead>Type name patterns</bridgehead>
+ <sect3>
+ <title>Type name patterns</title>
- <para>
- First, all type names are also type patterns. So
- <literal>Object</literal>, <literal>java.util.HashMap</literal>,
- <literal>Map.Entry</literal>, <literal>int</literal> are all type
- patterns.
- </para>
+ <para>
+ First, all type names are also type patterns. So
+ <literal>Object</literal>, <literal>java.util.HashMap</literal>,
+ <literal>Map.Entry</literal>, <literal>int</literal> are all type
+ patterns.
+ </para>
- <para>
- There is a special type name, *, which is also a type pattern. * picks out all
- types, including primitive types. So
- </para>
+ <para>
+ There is a special type name, *, which is also a type pattern. * picks out all
+ types, including primitive types. So
+ </para>
<programlisting>
-call(void foo(*))
+ call(void foo(*))
</programlisting>
- <para>
- picks out all call join points to void methods named foo, taking one
- argument of any type.
- </para>
+ <para>
+ picks out all call join points to void methods named foo, taking one
+ argument of any type.
+ </para>
- <para>
- Type names that contain the two wildcards "*" and
- "<literal>..</literal>" are also type patterns. The * wildcard matches
- zero or more characters characters except for ".", so it can be used
- when types have a certain naming convention. So
- </para>
+ <para>
+ Type names that contain the two wildcards "*" and
+ "<literal>..</literal>" are also type patterns. The * wildcard matches
+ zero or more characters characters except for ".", so it can be used
+ when types have a certain naming convention. So
+ </para>
<programlisting>
-handler(java.util.*Map)
+ handler(java.util.*Map)
</programlisting>
- <para>
- picks out the types java.util.Map and java.util.java.util.HashMap,
- among others, and
- </para>
+ <para>
+ picks out the types java.util.Map and java.util.java.util.HashMap,
+ among others, and
+ </para>
<programlisting>
-handler(java.util.*)
+ handler(java.util.*)
</programlisting>
- <para>
- picks out all types that start with "<literal>java.util.</literal>" and
- don't have any more "."s, that is, the types in the
- <literal>java.util</literal> package, but not inner types
- (such as java.util.Map.Entry).
- </para>
+ <para>
+ picks out all types that start with "<literal>java.util.</literal>" and
+ don't have any more "."s, that is, the types in the
+ <literal>java.util</literal> package, but not inner types
+ (such as java.util.Map.Entry).
+ </para>
- <para>
- The "<literal>..</literal>" 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
- </para>
+ <para>
+ The "<literal>..</literal>" 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
+ </para>
<programlisting>
-within(com.xerox..*)
+ within(com.xerox..*)
</programlisting>
- <para>
- picks out all join points where the code is in any type
- definition of a type whose name begins with "<literal>com.xerox.</literal>".
- </para>
+ <para>
+ picks out all join points where the code is in any type
+ definition of a type whose name begins with "<literal>com.xerox.</literal>".
+ </para>
- <bridgehead>Subtype patterns</bridgehead>
+ </sect3>
- <para>
- 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
- </para>
+ <sect3>
+ <title>Subtype patterns</title>
+
+ <para>
+ 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
+ </para>
<programlisting>
-call(Foo.new())
+ call(Foo.new())
</programlisting>
- <para>
- picks out all constructor call join points where an instance of exactly
- type Foo is constructed,
- </para>
+ <para>
+ picks out all constructor call join points where an instance of exactly
+ type Foo is constructed,
+ </para>
<programlisting>
-call(Foo+.new())
+ call(Foo+.new())
</programlisting>
- <para>
- picks out all constructor call join points where an instance of any
- subtype of Foo (including Foo itself) is constructed, and the unlikely
- </para>
+ <para>
+ picks out all constructor call join points where an instance of any
+ subtype of Foo (including Foo itself) is constructed, and the unlikely
+ </para>
<programlisting>
-call(*Handler+.new())
+ call(*Handler+.new())
</programlisting>
- <para>
- picks out all constructor call join points where an instance of any
- subtype of any type whose name ends in "Handler" is constructed.
- </para>
+ <para>
+ picks out all constructor call join points where an instance of any
+ subtype of any type whose name ends in "Handler" is constructed.
+ </para>
- <bridgehead>Array type patterns</bridgehead>
+ </sect3>
- <para>
- A type name pattern or subtype pattern can be followed by one or more
- sets of square brackets to make array type patterns. So
- <literal>Object[]</literal> is an array type pattern, and so is
- <literal>com.xerox..*[][]</literal>, and so is
- <literal>Object+[]</literal>.
- </para>
+ <sect3>
+ <title>Array type patterns</title>
- <bridgehead>Type patterns</bridgehead>
+ <para>
+ A type name pattern or subtype pattern can be followed by one or more
+ sets of square brackets to make array type patterns. So
+ <literal>Object[]</literal> is an array type pattern, and so is
+ <literal>com.xerox..*[][]</literal>, and so is
+ <literal>Object+[]</literal>.
+ </para>
+ </sect3>
- <para>
- Type patterns are built up out of type name patterns, subtype patterns,
- and array type patterns, and constructed with boolean operators
- <literal><![CDATA[&&]]></literal>, <literal>||</literal>, and
- <literal>!</literal>. So
- </para>
+ <sect3>
+ <title>Type patterns</title>
+
+ <para>
+ Type patterns are built up out of type name patterns, subtype patterns,
+ and array type patterns, and constructed with boolean operators
+ <literal><![CDATA[&&]]></literal>, <literal>||</literal>, and
+ <literal>!</literal>. So
+ </para>
<programlisting>
-staticinitialization(Foo || Bar)
+ staticinitialization(Foo || Bar)
</programlisting>
- <para>
- picks out the static initializer execution join points of either Foo or Bar,
- and
- </para>
+ <para>
+ picks out the static initializer execution join points of either Foo or Bar,
+ and
+ </para>
<programlisting>
-call((Foo+ <![CDATA[&&]]> ! Foo).new(..))
+ call((Foo+ <![CDATA[&&]]> ! Foo).new(..))
</programlisting>
- <para>
- picks out the constructor call join points when a subtype of Foo, but
- not Foo itself, is constructed.
- </para>
+ <para>
+ picks out the constructor call join points when a subtype of Foo, but
+ not Foo itself, is constructed.
+ </para>
+ </sect3>
</sect2>
</sect1>
<!-- ============================== -->
- <sect1 id="advice">
+ <sect1 id="semantics-advice">
<title>Advice</title>
- <itemizedlist>
- <listitem><literal>before(<replaceable>Formals</replaceable>): <replaceable>Pointcut</replaceable> { <replaceable>Body</replaceable> }</literal></listitem>
- <listitem><literal>after(<replaceable>Formals</replaceable>) returning [ (<replaceable>Formal</replaceable>) ]: <replaceable>Pointcut</replaceable> { <replaceable>Body</replaceable> }</literal></listitem>
- <listitem><literal>after(<replaceable>Formals</replaceable>) throwing [ (<replaceable>Formal</replaceable>) ]: <replaceable>Pointcut</replaceable> { <replaceable>Body</replaceable> }</literal></listitem>
- <listitem><literal>after(<replaceable>Formals</replaceable>) : <replaceable>Pointcut</replaceable> { <replaceable>Body</replaceable> }</literal></listitem>
- <listitem><literal><replaceable>Type</replaceable> around(<replaceable>Formals</replaceable>) [ throws <replaceable>TypeList</replaceable> ] : <replaceable>Pointcut</replaceable> { <replaceable>Body</replaceable> }</literal></listitem>
- </itemizedlist>
+ <para>
+ Each piece of advice is of the form
+
+ <blockquote>
+ <literal>[ strictfp ] <replaceable>AdviceSpec</replaceable> [
+ throws <replaceable>TypeList</replaceable> ] :
+ <replaceable>Pointcut</replaceable> {
+ <replaceable>Body</replaceable> } </literal>
+ </blockquote>
+
+ where <replaceable>AdviceSpec</replaceable> is one of
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <literal>before( <replaceable>Formals</replaceable> ) </literal>
+ </listitem>
+ <listitem>
+ <literal>after( <replaceable>Formals</replaceable> ) returning
+ [ ( <replaceable>Formal</replaceable> ) ] </literal>
+ </listitem>
+ <listitem>
+ <literal>after( <replaceable>Formals</replaceable> ) throwing [
+ ( <replaceable>Formal</replaceable> ) ] </literal>
+ </listitem>
+ <listitem>
+ <literal>after( <replaceable>Formals</replaceable> ) </literal>
+ </listitem>
+ <listitem>
+ <literal><replaceable>Type</replaceable>
+ around( <replaceable>Formals</replaceable> )</literal>
+ </listitem>
+ </itemizedlist>
<para>
Advice defines crosscutting behavior. It is defined in terms of
- pointcuts. The code of a piece of advice runs at every join point picked
- out by its pointcut. Exactly how the code runs depends on the kind of
- advice.
+ pointcuts. The code of a piece of advice runs at every join point
+ picked out by its pointcut. Exactly how the code runs depends on the
+ kind of advice.
</para>
<para>
@@ -1296,18 +1430,18 @@ call((Foo+ <![CDATA[&&]]> ! Foo).new(..))
</para>
<programlisting>
-aspect A {
- pointcut publicCall(): call(public Object *(..));
- after() returning (Object o): publicCall() {
- System.out.println("Returned normally with " + o);
- }
- after() throwing (Exception e): publicCall() {
- System.out.println("Threw an exception: " + e);
- }
- after(): publicCall(){
- System.out.println("Returned or threw an Exception");
- }
-}
+ aspect A {
+ pointcut publicCall(): call(public Object *(..));
+ after() returning (Object o): publicCall() {
+ System.out.println("Returned normally with " + o);
+ }
+ after() throwing (Exception e): publicCall() {
+ System.out.println("Threw an exception: " + e);
+ }
+ after(): publicCall(){
+ System.out.println("Returned or threw an Exception");
+ }
+ }
</programlisting>
<para>
@@ -1316,9 +1450,9 @@ aspect A {
</para>
<programlisting>
-after() returning: call(public Object *(..)) {
- System.out.println("Returned normally");
-}
+ after() returning: call(public Object *(..)) {
+ System.out.println("Returned normally");
+ }
</programlisting>
<para>
@@ -1327,9 +1461,9 @@ after() returning: call(public Object *(..)) {
</para>
<programlisting>
-after() returning (byte b): call(int String.length()) {
- // this is an error
-}
+ after() returning (byte b): call(int String.length()) {
+ // this is an error
+ }
</programlisting>
<para>
@@ -1359,11 +1493,11 @@ after() returning (byte b): call(int String.length()) {
</para>
<programlisting>
-aspect A {
- int around(): call(int C.foo()) {
- return 3;
- }
-}
+ aspect A {
+ int around(): call(int C.foo()) {
+ return 3;
+ }
+ }
</programlisting>
<para>
@@ -1372,7 +1506,7 @@ aspect A {
</para>
<programlisting>
-proceed( ... )
+ proceed( ... )
</programlisting>
<para>
@@ -1384,12 +1518,12 @@ proceed( ... )
<programlisting>
-aspect A {
- int around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
- int newi = proceed(i*2)
- return newi/2;
- }
-}
+ aspect A {
+ int around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
+ int newi = proceed(i*2)
+ return newi/2;
+ }
+ }
</programlisting>
<para>
@@ -1402,12 +1536,12 @@ aspect A {
</para>
<programlisting>
-aspect A {
- Object around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
- Integer newi = (Integer) proceed(i*2)
- return new Integer(newi.intValue() / 2);
- }
-}
+ aspect A {
+ Object around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
+ Integer newi = (Integer) proceed(i*2)
+ return new Integer(newi.intValue() / 2);
+ }
+ }
</programlisting>
<para>
@@ -1418,11 +1552,11 @@ aspect A {
</para>
<programlisting>
-aspect A {
- after() returning (int i): call(int C.foo()) {
- i = i * 2;
- }
-}
+ aspect A {
+ after() returning (int i): call(int C.foo()) {
+ i = i * 2;
+ }
+ }
</programlisting>
<para>
@@ -1457,22 +1591,22 @@ aspect A {
</para>
<programlisting>
-import java.io.FileNotFoundException;
-
-class C {
- int i;
-
- int getI() { return i; }
-}
-
-aspect A {
- before(): get(int C.i) {
- throw new FileNotFoundException();
- }
- before() throws FileNotFoundException: get(int C.i) {
- throw new FileNotFoundException();
- }
-}
+ import java.io.FileNotFoundException;
+
+ class C {
+ int i;
+
+ int getI() { return i; }
+ }
+
+ aspect A {
+ before(): get(int C.i) {
+ throw new FileNotFoundException();
+ }
+ before() throws FileNotFoundException: get(int C.i) {
+ throw new FileNotFoundException();
+ }
+ }
</programlisting>
<para>
@@ -1488,52 +1622,52 @@ aspect A {
<varlistentry>
<term>method call and execution</term>
<listitem>
- <para>the checked exceptions declared by the target method's
- <literal>throws</literal> clause.</para>
+ the checked exceptions declared by the target method's
+ <literal>throws</literal> clause.
</listitem>
</varlistentry>
<varlistentry>
<term>constructor call and execution</term>
<listitem>
- <para>the checked exceptions declared by the target constructor's
- <literal>throws</literal> clause.</para>
+ the checked exceptions declared by the target constructor's
+ <literal>throws</literal> clause.
</listitem>
</varlistentry>
<varlistentry>
<term>field get and set</term>
<listitem>
- <para>no checked exceptions can be thrown from these join points. </para>
+ no checked exceptions can be thrown from these join points.
</listitem>
</varlistentry>
<varlistentry>
<term>exception handler execution</term>
<listitem>
- <para>the exceptions that can be thrown by the target exception handler.</para>
+ the exceptions that can be thrown by the target exception handler.
</listitem>
</varlistentry>
<varlistentry>
<term>static initializer execution</term>
<listitem>
- <para>no checked exceptions can be thrown from these join points. </para>
+ no checked exceptions can be thrown from these join points.
</listitem>
</varlistentry>
<varlistentry>
- <term>pre-initialization, and initialization</term>
+ <term>pre-initialization and initialization</term>
<listitem>
- <para>any exception that is in the throws clause of
- <emphasis>all</emphasis> constructors of the initialized class. </para>
+ any exception that is in the throws clause of
+ <emphasis>all</emphasis> constructors of the initialized class.
</listitem>
</varlistentry>
<varlistentry>
<term>advice execution</term>
<listitem>
- <para>any exception that is in the throws clause of the advice. </para>
+ any exception that is in the throws clause of the advice.
</listitem>
</varlistentry>
@@ -1569,7 +1703,7 @@ aspect A {
<listitem>
Otherwise, if aspect A is a subaspect of aspect B, then all advice
defined in A has precedence over all advice defined in
- B. So, unless otherwise specified with
+ B. So, unless otherwise specified with
<literal>declare precedence</literal>, advice in a subaspect
has precedence over advice in a superaspect.
</listitem>
@@ -1598,15 +1732,14 @@ aspect A {
<para>These rules can lead to circularity, such as</para>
<programlisting>
-aspect A {
- before(): execution(void main(String[] args)) {}
- after(): execution(void main(String[] args)) {}
- before(): execution(void main(String[] args)) {}
-}
+ aspect A {
+ before(): execution(void main(String[] args)) {}
+ after(): execution(void main(String[] args)) {}
+ before(): execution(void main(String[] args)) {}
+ }
</programlisting>
<para>such circularities will result in errors signalled by the compiler. </para>
-
</sect3>
<sect3>
@@ -1642,7 +1775,6 @@ aspect A {
there is no further advice. Then the body of the advice will
run. </para>
</sect3>
-
</sect2>
<sect2>
@@ -1661,7 +1793,7 @@ aspect A {
<programlisting>
-pointcut publicCall(): call(public * *(..));
+ pointcut publicCall(): call(public * *(..));
</programlisting>
@@ -1705,7 +1837,7 @@ pointcut publicCall(): call(public * *(..));
</sect1>
- <sect1 id="staticCrosscutting">
+ <sect1 id="semantics-declare">
<title>Static crosscutting</title>
<para>
@@ -1715,14 +1847,13 @@ pointcut publicCall(): call(public * *(..));
inter-type member declarations and other <literal>declare</literal> forms.
</para>
-
<sect2>
<title>Inter-type member declarations</title>
- <para>
- AspectJ allows the declaration of members by aspects that are
- associated with other types.
- </para>
+ <para>
+ AspectJ allows the declaration of members by aspects that are
+ associated with other types.
+ </para>
<para>
An inter-type method declaration looks like
@@ -1730,18 +1861,18 @@ pointcut publicCall(): call(public * *(..));
<itemizedlist>
<listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
+ [ <replaceable>Modifiers</replaceable> ]
<replaceable>Type</replaceable> <replaceable>OnType</replaceable>
.
- <replaceable>Id</replaceable>(<replaceable>Formals</replaceable>)
- [ <replaceable>ThrowsClause</replaceable> ]
+ <replaceable>Id</replaceable>(<replaceable>Formals</replaceable>)
+ [ <replaceable>ThrowsClause</replaceable> ]
{ <replaceable>Body</replaceable> }</literal></listitem>
- <listitem><literal>abstract
- [ <replaceable>Modifiers</replaceable> ]
+ <listitem><literal>abstract
+ [ <replaceable>Modifiers</replaceable> ]
<replaceable>Type</replaceable> <replaceable>OnType</replaceable>
. <replaceable>Id</replaceable>(<replaceable>Formals</replaceable>)
- [ <replaceable>ThrowsClause</replaceable> ]
+ [ <replaceable>ThrowsClause</replaceable> ]
;
</literal></listitem>
</itemizedlist>
@@ -1754,17 +1885,17 @@ pointcut publicCall(): call(public * *(..));
</para>
<programlisting>
-interface Iface {}
-
-aspect A {
- private void Iface.m() {
- System.err.println("I'm a private method on an interface");
- }
- void worksOnI(Iface iface) {
- // calling a private method on an interface
- iface.m();
- }
-}
+ interface Iface {}
+
+ aspect A {
+ private void Iface.m() {
+ System.err.println("I'm a private method on an interface");
+ }
+ void worksOnI(Iface iface) {
+ // calling a private method on an interface
+ iface.m();
+ }
+ }
</programlisting>
<para>
@@ -1773,10 +1904,10 @@ aspect A {
<itemizedlist>
<listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>OnType</replaceable> . new (
- <replaceable>Formals</replaceable> )
- [ <replaceable>ThrowsClause</replaceable> ]
+ [ <replaceable>Modifiers</replaceable> ]
+ <replaceable>OnType</replaceable> . new (
+ <replaceable>Formals</replaceable> )
+ [ <replaceable>ThrowsClause</replaceable> ]
{ <replaceable>Body</replaceable> }</literal></listitem>
</itemizedlist>
@@ -1787,20 +1918,29 @@ aspect A {
</para>
<para>
+ Note that in the Java language, classes that define no constructors
+ have an implicit no-argument constructor that just calls
+ <literal>super()</literal>. This means that attempting to declare
+ a no-argument inter-type constructor on such a class may result in
+ a conflict, even though it <emphasis>looks</emphasis> like no
+ constructor is defined.
+ </para>
+
+ <para>
An inter-type field declaration looks like one of
</para>
<itemizedlist>
<listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable>
- <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>
- = <replaceable>Expression</replaceable>;</literal></listitem>
+ [ <replaceable>Modifiers</replaceable> ]
+ <replaceable>Type</replaceable>
+ <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>
+ = <replaceable>Expression</replaceable>;</literal></listitem>
<listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable>
- <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>;</literal></listitem>
+ [ <replaceable>Modifiers</replaceable> ]
+ <replaceable>Type</replaceable>
+ <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>;</literal></listitem>
</itemizedlist>
<para>
@@ -1809,6 +1949,12 @@ aspect A {
<replaceable>OnType</replaceable> is an interface. Even if the field is
neither public, nor static, nor final.
</para>
+
+ <para>
+ The initializer, if any, of an inter-type field definition runs
+ before the class-local initializers defined in its target class.
+ </para>
+
</sect2>
<para>
@@ -1843,12 +1989,12 @@ aspect A {
supports) is very different from inserting a private method declaration
into another class. The former allows access only from the declaring
aspect, while the latter would allow access only from the target type.
- Java serialization, for example, uses the presense of a private method
- <literal>void writeObject(ObjectOutputStream)</literal> for the
- implementation of <literal>java.io.Serializable</literal>. A private
- inter-type declaration of that method would not fulfill this
- requirement, since it would be private to the aspect, not private to
- the target type.
+ Java serialization, for example, uses the presense of a private method
+ <literal>void writeObject(ObjectOutputStream)</literal> for the
+ implementation of <literal>java.io.Serializable</literal>. A private
+ inter-type declaration of that method would not fulfill this
+ requirement, since it would be private to the aspect, not private to
+ the target type.
</para>
</sect2>
@@ -1863,13 +2009,13 @@ aspect A {
</para>
<programlisting>
-aspect A {
- private Registry otherPackage.*.r;
- public void otherPackage.*.register(Registry r) {
- r.register(this);
- this.r = r;
- }
-}
+ aspect A {
+ private Registry otherPackage.*.r;
+ public void otherPackage.*.register(Registry r) {
+ r.register(this);
+ this.r = r;
+ }
+ }
</programlisting>
<para>
@@ -1895,7 +2041,7 @@ aspect A {
</para>
<programlisting>
-this.r = r
+ this.r = r
</programlisting>
<para>
@@ -1944,12 +2090,12 @@ this.r = r
<para>
An aspect may change the inheritance hierarchy of a system by changing
- the a superclass of a type or adding a superinterface onto a type, with
+ the superclass of a type or adding a superinterface onto a type, with
the <literal>declare parents</literal> form.
</para>
<itemizedlist>
- <listitem><literal>declare parents: <replaceable>TypePattern</replaceable> extends <replaceable>TypeList</replaceable>;</literal></listitem>
+ <listitem><literal>declare parents: <replaceable>TypePattern</replaceable> extends <replaceable>Type</replaceable>;</literal></listitem>
<listitem><literal>declare parents: <replaceable>TypePattern</replaceable> implements <replaceable>TypeList</replaceable>;</literal></listitem>
</itemizedlist>
@@ -1963,10 +2109,10 @@ this.r = r
</para>
<programlisting>
-aspect A {
- declare parents: SomeClass implements Runnable;
- public void SomeClass.run() { ... }
-}
+ aspect A {
+ declare parents: SomeClass implements Runnable;
+ public void SomeClass.run() { ... }
+ }
</programlisting>
</sect2>
@@ -1996,13 +2142,13 @@ aspect A {
</para>
<programlisting>
- Object M O
- \ / \ /
- C N Q
- \ / /
- D P
- \ /
- E
+ Object M O
+ \ / \ /
+ C N Q
+ \ / /
+ D P
+ \ /
+ E
</programlisting>
<para>
@@ -2010,7 +2156,7 @@ aspect A {
</para>
<programlisting>
- Object M C O N D Q P E
+ Object M C O N D Q P E
</programlisting>
</sect2>
@@ -2052,9 +2198,9 @@ aspect A {
<para>For example, the aspect</para>
<programlisting>
-aspect A {
- declare soft: Exception: execution(void main(String[] args));
-}
+ aspect A {
+ declare soft: Exception: execution(void main(String[] args));
+ }
</programlisting>
<para>Would, at the execution join point, catch any
@@ -2065,14 +2211,14 @@ aspect A {
<para>This is similar to what the following advice would do</para>
<programlisting>
-aspect A {
- void around() execution(void main(String[] args)) {
- try { proceed(); }
- catch (Exception e) {
- throw new org.aspectj.lang.SoftException(e);
- }
- }
-}
+ aspect A {
+ void around() execution(void main(String[] args)) {
+ try { proceed(); }
+ catch (Exception e) {
+ throw new org.aspectj.lang.SoftException(e);
+ }
+ }
+ }
</programlisting>
<para>except, in addition to wrapping the exception, it also affects
@@ -2089,56 +2235,148 @@ aspect A {
</para>
<itemizedlist>
- <listitem><literal>declare precedence : <replaceable>TypePatternList</replaceable></literal></listitem>
+ <listitem><literal>declare precedence :
+ <replaceable>TypePatternList</replaceable> ; </literal></listitem>
</itemizedlist>
- <para>This signifies that if any join point has advice from two concrete
- aspects matched by some pattern in
- <replaceable>TypePatternList</replaceable>, then the precence of the
- advice will be the order of in the list. </para>
+ <para>This signifies that if any join point has advice from two
+ concrete aspects matched by some pattern in
+ <replaceable>TypePatternList</replaceable>, then the precedence of
+ the advice will be the order of in the list. </para>
<para>In <replaceable>TypePatternList</replaceable>, the wildcard "*" can
appear at most once, and it means "any type not matched by any other
pattern in the list". </para>
- <para>For example, the constraints that (1) aspects that have Security as
- part 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:</para>
+ <para>For example, the constraints that (1) aspects that have
+ Security as part 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:</para>
<programlisting>
- declare precedence: *..*Security*, Logging+, *;
+ declare precedence: *..*Security*, Logging+, *;
</programlisting>
<para>
For another example, the CountEntry aspect might want to count the
- entry to methods in the current package accepting a Type object as its
- first argument. However, it should count all entries, even those that
- the aspect DisallowNulls causes to throw exceptions. This can be
- accomplished by stating that CountEntry has precedence over
- DisallowNulls. This declaration could be in either aspect, or in
- another, ordering aspect:
+ entry to methods in the current package accepting a Type object as
+ its first argument. However, it should count all entries, even
+ those that the aspect DisallowNulls causes to throw exceptions.
+ This can be accomplished by stating that CountEntry has precedence
+ over DisallowNulls. This declaration could be in either aspect, or
+ in another, ordering aspect:
</para>
+<programlisting>
+ aspect Ordering {
+ declare precedence: CountEntry, DisallowNulls;
+ }
+ aspect DisallowNulls {
+ pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
+ before(Type obj): allTypeMethods(obj) {
+ if (obj == null) throw new RuntimeException();
+ }
+ }
+ aspect CountEntry {
+ pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
+ static int count = 0;
+ before(): allTypeMethods(Type) {
+ count++;
+ }
+ }
+</programlisting>
+
+ <sect3>
+ <title>Various cycles</title>
+
+ <para>
+ It is an error for any aspect to be matched by more than one
+ TypePattern in a single decare precedence, so:
+ </para>
+
+<programlisting>
+ declare precedence: A, B, A ; // error
+</programlisting>
+
+ <para>
+ However, multiple declare precedence forms may legally have this
+ kind of circularity. For example, each of these declare
+ precedence is perfectly legal:
+ </para>
+
+<programlisting>
+ declare precedence: B, A;
+ declare precedence: A, B;
+</programlisting>
+
+ <para>
+ And a system in which both constraints are active may also be
+ legal, so long as advice from A and B don't share a join
+ point. So this is an idiom that can be used to enforce that A and
+ B are strongly independent.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Applies to concrete aspects</title>
+
+ <para>
+ Consider the following library aspects:
+ </para>
+
+<programlisting>
+ abstract aspect Logging {
+ abstract pointcut logged();
+
+ before(): logged() {
+ System.err.println("thisJoinPoint: " + thisJoinPoint);
+ }
+ }
+
+ aspect aspect MyProfiling {
+ abstract pointcut profiled();
+
+ Object around(): profiled() {
+ long beforeTime = System.currentTimeMillis();
+ try {
+ return proceed();
+ } finally {
+ long afterTime = System.currentTimeMillis();
+ addToProfile(thisJoinPointStaticPart,
+ afterTime - beforeTime);
+ }
+ }
+ abstract void addToProfile(
+ org.aspectj.JoinPoint.StaticPart jp,
+ long elapsed);
+ }
+</programlisting>
+
+ <para>
+ In order to use either aspect, they must be extended with
+ concrete 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
+ </para>
<programlisting>
-aspect Ordering {
- declare precedence: CountEntry, DisallowNulls;
-}
-aspect DisallowNulls {
- pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
- before(Type obj): allTypeMethods(obj) {
- if (obj == null) throw new RuntimeException();
- }
-}
-aspect CountEntry {
- pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
- static int count = 0;
- before(): allTypeMethods(Type) {
- count++;
- }
-}
+ declare precedence: Logging, Profiling;
</programlisting>
+
+ <para>
+ has no effect, but both
+ </para>
+
+<programlisting>
+ declare precedence: MyLogging, MyProfiling;
+ declare precedence: Logging+, Profiling+;
+</programlisting>
+
+ <para>
+ are meaningful.
+ </para>
+ </sect3>
</sect2>
@@ -2167,7 +2405,7 @@ aspect CountEntry {
</sect2>
</sect1>
- <sect1 id="aspects">
+ <sect1 id="semantics-aspects">
<title>Aspects</title>
<para>
@@ -2348,6 +2586,50 @@ aspect CountEntry {
control flow.
</para>
</sect3>
+
+ <sect3>
+ <title>Aspect instantiation and advice</title>
+
+ <para>
+ 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:
+ </para>
+
+<programlisting>
+ public class Client
+ {
+ public static void main(String[] args) {
+ Client c = new Client();
+ }
+ }
+
+ aspect Watchcall {
+ pointcut myConstructor(): execution(new(..));
+
+ before(): myConstructor() {
+ System.err.println("Entering Constructor");
+ }
+ }
+</programlisting>
+
+ <para>
+ The before advice should run before the execution of all
+ constructors in the system. It must run in the context of an
+ instance of the Watchcall aspect. The only way to get such an
+ instance is to have Watchcall's default constructor execute. But
+ before that executes, we need to run the before advice...
+ </para>
+
+ <para>
+ There is no general way to detect these kinds of circularities at
+ compile time. If advice runs before its aspect is instantiated,
+ AspectJ will throw a <ulink
+ url="../api/org/aspectj/lang/NoAspectBoundException.html">
+ <literal>org.aspectj.lang.NoAspectBoundException</literal></ulink>.
+ </para>
+ </sect3>
</sect2>
<sect2>
@@ -2373,18 +2655,17 @@ aspect CountEntry {
access to all members, even private ones.
</para>
-
<programlisting>
-class C {
- private int i = 0;
- void incI(int x) { i = i+x; }
-}
-privileged aspect A {
- static final int MAX = 1000;
- before(int x, C c): call(void C.incI(int)) <![CDATA[&&]]> target(c) <![CDATA[&&]]> args(x) {
- if (c.i+x &gt; MAX) throw new RuntimeException();
- }
-}
+ class C {
+ private int i = 0;
+ void incI(int x) { i = i+x; }
+ }
+ privileged aspect A {
+ static final int MAX = 1000;
+ before(int x, C c): call(void C.incI(int)) <![CDATA[&&]]> target(c) <![CDATA[&&]]> args(x) {
+ if (c.i+x &gt; MAX) throw new RuntimeException();
+ }
+ }
</programlisting>
<para>
@@ -2399,16 +2680,16 @@ privileged aspect A {
</para>
<programlisting>
-class C {
- private int i = 0;
- void foo() { }
-}
-privileged aspect A {
- private int C.i = 999;
- before(C c): call(void C.foo()) target(c) {
- System.out.println(c.i);
- }
-}
+ class C {
+ private int i = 0;
+ void foo() { }
+ }
+ privileged aspect A {
+ private int C.i = 999;
+ before(C c): call(void C.foo()) target(c) {
+ System.out.println(c.i);
+ }
+ }
</programlisting>
<para>
@@ -2418,17 +2699,11 @@ privileged aspect A {
fields even if it were not privileged.
</para>
+ <para>
+ Note that a privileged aspect can access private inter-type
+ declarations made by other aspects, since they are simply
+ considered private members of that other aspect.
+ </para>
</sect2>
-
- </sect1>
-
+ </sect1>
</appendix>
-
-<!--
-Local variables:
-compile-command: "java sax.SAXCount -v progguide.xml && java com.icl.saxon.StyleSheet -w0 progguide.xml progguide.html.xsl"
-fill-column: 79
-sgml-local-ecat-files: progguide.ced
-sgml-parent-document:("progguide.sgml" "book" "appendix")
-End:
--->