diff options
Diffstat (limited to 'docs/adk15ProgGuideDB/joinpointsignatures.xml')
-rw-r--r-- | docs/adk15ProgGuideDB/joinpointsignatures.xml | 425 |
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> |