summaryrefslogtreecommitdiffstats
path: root/docs/adk15ProgGuideDB/joinpointsignatures.xml
diff options
context:
space:
mode:
Diffstat (limited to 'docs/adk15ProgGuideDB/joinpointsignatures.xml')
-rw-r--r--docs/adk15ProgGuideDB/joinpointsignatures.xml425
1 files changed, 390 insertions, 35 deletions
diff --git a/docs/adk15ProgGuideDB/joinpointsignatures.xml b/docs/adk15ProgGuideDB/joinpointsignatures.xml
index 0c3473034..fbf59e146 100644
--- a/docs/adk15ProgGuideDB/joinpointsignatures.xml
+++ b/docs/adk15ProgGuideDB/joinpointsignatures.xml
@@ -1,23 +1,212 @@
<chapter id="jpsigs" xreflabel="Join Point Signatures">
<title>Join Point Signatures</title>
+
+ <para>
+ Many of the extensions to the AspectJ language to address the new features of
+ Java 5 are derived from a simple set of principles for join point
+ matching. In this section, we outline these principles as a foundation
+ for understanding the matching rules in the presence of annotations,
+ generics, covariance, varargs, and autoboxing.
+ </para>
- <para>To understand join point matching for annotations, generics, and
- covariance, it is first necessary to understand the concepts of
- join point signatures and join point signature matching, for call and
- execution join points.</para>
+ <sect1>
+ <title>Join Point Matching</title>
+
+ <para>AspectJ supports 11 different kinds of join points. These are
+ the <literal>method call, method execution, constructor call,
+ constructor execution, field get, field set, pre-initialization,
+ initialization, static initialization, handler,</literal> and
+ <literal>advice execution</literal> join points.</para>
+
+ <para>The <emphasis>kinded</emphasis> pointcut designators match
+ based on the kind of a join point. These are the <literal>call,
+ execution, get, set, preinitialization, initialization,
+ staticinitialization, handler,</literal> and <literal>adviceexecution</literal>
+ designators.</para>
+
+ <para>A kinded pointcut is written using patterns, some of which
+ match based on <emphasis>signature</emphasis>, and some of which
+ match based on <emphasis>modifiers</emphasis>. For example, in
+ the <literal>call</literal> pointcut designator:</para>
+
+ <programlisting><![CDATA[
+ call(ModifierPattern TypePattern TypePattern.IdPattern(TypePatternList) ThrowsPattern)
+ ]]></programlisting>
+
+ <para>the modifiers matching patterns are <literal>ModifierPattern</literal>
+ and <literal>ThrowsPattern</literal>, and the signature matching patterns
+ are <literal>TypePattern TypePattern.IdPattern(TypePatternList)</literal>.
+ </para>
+
+ <para>
+ A join point has potentially multiple signatures, but only one set of
+ modifiers. <emphasis>A kinded primitive pointcut matches a particular join point
+ if and only if</emphasis>:
+ </para>
+
+ <orderedlist>
+ <listitem>They are of the same kind</listitem>
+ <listitem>The signature pattern (exactly) matches at least one
+ signature of the join point</listitem>
+ <listitem>The modifiers pattern matches the modifiers of the
+ join point</listitem>
+ </orderedlist>
+
+ <para>These rules make it very easily to quickly determine whether a
+ given pointcut matches a given join point. In the next two sections,
+ we describe what the signature(s) of a join point are, and what the
+ modifiers of a join point are.</para>
+
+ </sect1>
<sect1>
- <title>Join Point Signatures for Call Join Points</title>
+ <title>Join Point Signatures</title>
+
+ <para>Call and execution join points may potentially have multiple
+ signatures. All other join points have exactly one signature. The
+ following table summarizes the constituent parts of a join point
+ signature for the different kinds of join point.</para>
+
+ <informaltable>
+ <tgroup cols="7">
+ <thead>
+ <row>
+ <entry>Join Point Kind</entry>
+ <entry>Return Type</entry>
+ <entry>Declaring Type</entry>
+ <entry>Id</entry>
+ <entry>Parameter Types</entry>
+ <entry>Field Type</entry>
+ <entry>Exception Type</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Method call</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Method execution</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Constructor call</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Constructor execution</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Field get</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Field set</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Pre-initialization</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Initialization</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Static initialization</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Handler</entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ <entry>+</entry>
+ </row>
+ <row>
+ <entry>Advice execution</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry>+</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
- <para>A call join point can have more than one signature. For a
- call pointcut expression to match a given call join point, at
- least one of the join point signatures must be matched by the
- pointcut's signature pattern.</para>
+ <para>Note that whilst an advice excetution join point has a
+ signature comprising the declaring type of the advice and the
+ advice parameter types, the <literal>adviceexecution</literal>
+ pointcut designator does not support matching based on this
+ signature.</para>
+ <para>The signatures for most of the join point kinds should be
+ self-explanatory, except for method call and execution
+ join points, which can have multiple signatures. Each signature of
+ a method call or execution join point has the same id and parameter
+ types, but the declaring type and return type (with covariance) may vary.
+ </para>
+
+ <para>The following sections examine signatures for method call and
+ execution join points in more detail.</para>
+
+ <sect2>
+ <title>Method call join point signatures</title>
+
<para>
For a call join point where a call is made to a method
- <literal>m(args)</literal> on a target type <literal>T</literal> (where
+ <literal>m(parameter_types)</literal> on a target type <literal>T</literal> (where
<literal>T</literal> is the static type of the target):
</para>
@@ -27,12 +216,12 @@
]]></programlisting>
<para>
- Then the signature <literal>R(T) T.m(args)</literal> is a signature
+ Then the signature <literal>R(T) T.m(parameter_types)</literal> is a signature
of the call join point, where <literal>R(T)</literal> is the return
- type of <literal>m</literal> in <literal>T</literal>, and
- <literal>args</literal> represents the types of the arguments to
+ type of <literal>id</literal> in <literal>T</literal>, and
+ <literal>parameter_types</literal> are the parameter types of
<literal>m</literal>. If <literal>T</literal> itself does not
- declare a definition of <literal>m(args)</literal>, then
+ declare a definition of <literal>m(parameter_types)</literal>, then
<literal>R(T)</literal> is the return type in the definition of
<literal>m</literal> that <literal>T</literal> inherits. Given the
call above, and the definition of <literal>T.m</literal>:
@@ -51,21 +240,21 @@
R' m(String s) {...}
}
- class T extends S {
+ class T extends S {}
]]></programlisting>
<para>Then <literal>R' T.m(String)</literal> is a signature of the
- call join point for <literal>t.m("hello")</literal></para>.
+ call join point for <literal>t.m("hello")</literal>.</para>
<para>
For each ancestor (super-type) <literal>A</literal> of <literal>T</literal>,
- if <literal>m(args)</literal> is defined for that super-type, then
- <literal>R(A) A.m(args)</literal> is a signature of the call join
+ if <literal>m(parameter_types)</literal> is defined for that super-type, then
+ <literal>R(A) A.m(parameter_types)</literal> is a signature of the call join
point, where <literal>R(A)</literal> is the return type of <literal>
- m(args)</literal> as defined in <literal>A</literal>, or as inherited
+ m(parameter_types)</literal> as defined in <literal>A</literal>, or as inherited
by <literal>A</literal> if <literal>A</literal> itself does not
- provide a definition of <literal>m(args)</literal>.
+ provide a definition of <literal>m(parameter_types)</literal>.
</para>
<para>
@@ -79,21 +268,18 @@
]]></programlisting>
<para>are all additional signatures for the call join point arising
- from the call <literal>t.m("hello")</literal>. Thus the call
- join point has four signatures in total. Amongst these signatures,
- we say that the <emphasis>most-specific signature</emphasis> is the
- signature with the most-specific declaring type - that is, the
- signature of the static type of the target of the call
- (<literal>R' T.m(String)</literal>) in this case.</para>
+ from the call <literal>t.m("hello")</literal>. Thus this call
+ join point has four signatures in total. Every signature has the same
+ id and parameter types, and a different declaring type.</para>
- </sect1>
+ </sect2>
- <sect1>
- <title>Join Point Signatures for Execution Join Points</title>
+ <sect2>
+ <title>Method execution join point signatures</title>
<para>Join point signatures for execution join points are defined
in a similar manner to signatures for call join points. Given the
- same hierarchy as in the call example in the previous section:
+ hierarchy:
</para>
@@ -110,22 +296,191 @@
R' m(String s) {...}
}
- class T extends S {
+ class T extends S { }
+
+ class U extends T {
+ R' m(String s) {...}
+ }
]]></programlisting>
<para>Then the execution join point signatures arising as a result
- of the call to <literal>t.m("hello")</literal> are: </para>
+ of the call to <literal>u.m("hello")</literal> are: </para>
+ <programlisting><![CDATA[
+ R' U.m(String)
+ R' S.m(String)
+ R P.m(String)
+ R Q.m(String)
+ ]]></programlisting>
+
+ <para>Each signature has the same id and parameter types, and a
+ different declaring type. There is one signature for each type
+ that provides its own declaration of the method. Hence in this
+ example there is no signature <literal>R' T.m(String)</literal>
+ as <literal>T</literal> does not provide its own declaration of
+ the method.</para>
+ </sect2>
+
</sect1>
<sect1>
- <title>Pointcut matching based on Join Point Signatures</title>
+ <title>Join Point Modifiers</title>
+
+ <para>Every join point has a single set of modifiers - these include
+ the standard Java modifiers such as <literal>public, private,
+ static, abstract</literal> etc., any annotations, and the throws
+ clauses of methods and constructors.</para>
+
+ <para>
+ For the different join point kinds, the modifiers are:
+ </para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Join Point Kind</entry>
+ <entry>Join Point Modifiers</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Method call</entry>
+ <entry>The modifiers of the method picked out by Java as
+ the static target of the method call.</entry>
+ </row>
+ <row>
+ <entry>Method execution</entry>
+ <entry>The modifiers of the method that is executing.</entry>
+ </row>
+ <row>
+ <entry>Constructor call</entry>
+ <entry>The modifiers of the constructor being called.</entry>
+ </row>
+ <row>
+ <entry>Constructor execution</entry>
+ <entry>The modifiers of the constructor executing.</entry>
+ </row>
+ <row>
+ <entry>Field get</entry>
+ <entry>The modifiers of the field being accessed.</entry>
+ </row>
+ <row>
+ <entry>Field set</entry>
+ <entry>The modifiers of the field being set.</entry>
+ </row>
+ <row>
+ <entry>Pre-initialization</entry>
+ <entry>The modifiers of the first constructor executing in
+ this constructor chain.</entry>
+ </row>
+ <row>
+ <entry>Initialization</entry>
+ <entry>The modifiers of the first constructor executing in
+ this constructor chain.</entry>
+ </row>
+ <row>
+ <entry>Static initialization</entry>
+ <entry>The modifiers of the type being initialized.</entry>
+ </row>
+ <row>
+ <entry>Handler</entry>
+ <entry>No modifiers.</entry>
+ </row>
+ <row>
+ <entry>Advice execution</entry>
+ <entry>The modifiers of the advice being executed.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>For example, given the following types</para>
+
+ <programlisting><![CDATA[
+ public class X {
+ @Foo
+ protected void doIt() {...}
+ }
+
+ public class Y extends X {
+ public void doIt() {...}
+ }
+ ]]></programlisting>
+
+ <para>Then the modifiers for a call to <literal>(Y y) y.doIt()</literal>
+ are simply <literal>{public}</literal>. The modifiers for a call to
+ <literal>(X x) x.doIt()</literal> are <literal>{@Foo,protected}</literal>.
+ </para>
- <para>Explain signature + modifiers split, plus notion of "most-specific"
- join point.</para>
</sect1>
+ <sect1>
+ <title>Summary of Join Point Matching</title>
+
+ <para>
+ A join point has potentially multiple signatures, but only one set of
+ modifiers. <emphasis>A kinded primitive pointcut matches a particular join point
+ if and only if</emphasis>:
+ </para>
+
+ <orderedlist>
+ <listitem>They are of the same kind</listitem>
+ <listitem>The signature pattern (exactly) matches at least one
+ signature of the join point</listitem>
+ <listitem>The modifiers pattern matches the modifiers of the
+ join point</listitem>
+ </orderedlist>
+
+ <para>Given the hierarchy</para>
+
+ <programlisting><![CDATA[
+ interface Q {
+ R m(String s);
+ }
+
+ class P implements Q {
+ @Foo
+ public R m(String s) {...}
+ }
+
+ class S extends P {
+ @Bar
+ public R' m(String s) {...}
+ }
+
+ class T extends S {}
+
+ ]]></programlisting>
+
+ <para>and the program fragment:</para>
+
+ <programlisting><![CDATA[
+ P p = new P();
+ S s = new S();
+ T t = new T();
+ ...
+ p.m("hello");
+ s.m("hello");
+ t.m("hello");
+ ]]></programlisting>
+
+ <para>
+ The the pointcut <literal>call(@Foo R P.m(String))</literal> matches the
+ call <literal>p.m("hello")</literal> since both the signature and the
+ modifiers match. It does not match the call <literal>s.m("hello")</literal>
+ because even though the signature pattern matches one of the signatures
+ of the join point, the modifiers pattern does not match the modifiers of
+ the method m in S which is the static target of the call.
+ </para>
+
+ <para>The pointcut <literal>call(R' m(String))</literal> matches the
+ calls <literal>t.m("hello")</literal> and <literal>s.m("hello")</literal>.
+ It does not match the call <literal>p.m("hello")</literal> since the
+ signature pattern does not match any signature for the call join point
+ of m in P.</para>
+ </sect1>
</chapter>