1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420 |
- <chapter id="annotations" xreflabel="Annotations">
-
- <title>Annotations</title>
-
- <sect1 id="annotations-inJava5">
- <title>Annotations in Java 5</title>
-
- <para>
- This section provides the essential information about annotations in
- Java 5 needed to understand how annotations are treated in AspectJ 5.
- For a full introduction to annotations in Java, please see the
- documentation for the Java 5 SDK.
- </para>
-
- <sect2 id="using-annotations" xreflabel="using-annotations">
- <title>Using Annotations</title>
-
- <para>
- Java 5 introduces <emphasis>annotation types</emphasis> which can
- be used to express metadata relating to program members in the
- form of <emphasis>annotations</emphasis>. Annotations in Java 5
- can be applied to package and type declarations (classes,
- interfaces, enums, and annotations), constructors, methods,
- fields, parameters, and variables. Annotations are specified in the
- program source by using the <literal>@</literal> symbol. For example,
- the following piece of code uses the <literal>@Deprecated</literal>
- annotation to indicate that the <literal>obsoleteMethod()</literal>
- has been deprecated:
- </para>
-
- <programlisting><![CDATA[
- @Deprecated
- public void obsoleteMethod() { ... }
- ]]> </programlisting>
-
- <para>
- Annotations may be <emphasis>marker annotations</emphasis>,
- <emphasis>single-valued annotations</emphasis>, or
- <emphasis>multi-valued annotations</emphasis>.
- Annotation types with no members or that provide default values
- for all members may be used simply as marker annotations, as in
- the deprecation example above. Single-value annotation types have
- a single member, and the annotation may be written in one of
- two equivalent forms:
- </para>
-
- <programlisting><![CDATA[
- @SuppressWarnings({"unchecked"})
- public void someMethod() {...}
- ]]> </programlisting>
-
- <para>
- or
- </para>
-
- <programlisting><![CDATA[
- @SuppressWarnings(value={"unchecked"})
- public void someMethod() {...}
- ]]> </programlisting>
-
- <para>
- Multi-value annotations must use the <literal>member-name=value
- </literal> syntax to specify annotation values. For example:
- </para>
-
- <programlisting><![CDATA[
- @Authenticated(role="supervisor",clearanceLevel=5)
- public void someMethod() {...}
- ]]> </programlisting>
-
- </sect2>
-
- <sect2 id="retention-policies" xreflabel="retention-policies">
- <title>Retention Policies</title>
-
- <para>
- Annotations can have one of three retention policies:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>Source-file retention</term>
- <listitem>
- <para>
- Annotations with source-file retention are read by the
- compiler during the compilation process, but are not
- rendered in the generated <literal>.class</literal> files.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Class-file retention</term>
- <listitem>
- <para>
- This is the default retention policy. Annotations
- with class-file retention are read by the compiler
- and also retained in the generated <literal>
- .class</literal> files.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Runtime retention</term>
- <listitem>
- <para>
- Annotations with runtime retention are read by the
- compiler, retained in the generated <literal>
- .class</literal> files, and also made available
- at runtime.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>Local variable annotations are not retained in class files (or at runtime)
- regardless of the retention policy set on the annotation type. See JLS 9.6.1.2.</para>
- </sect2>
-
- <sect2 id="accessing-annotations-at-runtime" xreflabel="accessing-annotations-at-runtime">
- <title>Accessing Annotations at Runtime</title>
-
- <para>
- Java 5 supports a new interface,
- <literal>java.lang.reflect.AnnotatedElement</literal>, that is
- implemented by the reflection classes in Java (<literal>Class</literal>,
- <literal>Constructor</literal>,
- <literal>Field</literal>, <literal>Method</literal>, and
- <literal>Package</literal>). This interface gives you access
- to annotations <emphasis>that have runtime retention</emphasis> via
- the <literal>getAnnotation</literal>, <literal>getAnnotations</literal>,
- and <literal>isAnnotationPresent</literal>. Because annotation types are
- just regular Java classes, the annotations returned by these methods
- can be queried just like any regular Java object.
- </para>
-
- </sect2>
-
- <sect2 id="annotation-inheritance" xreflabel="annotation-inheritance">
- <title>Annotation Inheritance</title>
-
- <para>
- It is important to understand the rules relating to inheritance of
- annotations, as these have a bearing on join point matching
- based on the presence or absence of annotations.
- </para>
-
- <para>
- By default annotations are <emphasis>not</emphasis> inherited. Given
- the following program
- </para>
-
- <programlisting><![CDATA[
- @MyAnnotation
- class Super {
- @Oneway public void foo() {}
- }
-
- class Sub extends Super {
- public void foo() {}
- }
- ]]> </programlisting>
-
- <para>
- Then <literal>Sub</literal> <emphasis>does not</emphasis> have
- the <literal>MyAnnotation</literal> annotation, and
- <literal>Sub.foo()</literal> is not an <literal>@Oneway</literal>
- method, despite the fact that it overrides
- <literal>Super.foo()</literal> which is.
- </para>
-
- <para>
- If an annotation type has the meta-annotation <literal>@Inherited</literal>
- then an annotation of that type on a <emphasis>class</emphasis> will cause
- the annotation to be inherited by sub-classes. So, in the example
- above, if the <literal>MyAnnotation</literal> type had the
- <literal>@Inherited</literal> attribute, then <literal>Sub</literal>
- would have the <literal>MyAnnotation</literal> annotation.
- </para>
-
- <para>
- <literal>@Inherited</literal> annotations are not inherited when used to
- annotate anything other than a type. A type
- that implements one or more interfaces never inherits any annotations from
- the interfaces it implements.
- </para>
-
- </sect2>
- </sect1>
-
- <!-- ============================== -->
-
- <sect1 id="annotations-aspectmembers">
- <title>Annotating Aspects</title>
-
- <para>
- AspectJ 5 supports annotations on aspects, and on method, field,
- constructor, advice, and inter-type declarations within aspects.
- Method and advice parameters may also be annotated.
- Annotations are not permitted on pointcut declarations or on
- <literal>declare</literal> statements.
- </para>
-
- <para>
- The following example illustrates the use of annotations in aspects:
- </para>
-
-
- <programlisting><![CDATA[
- @AspectAnnotation
- public abstract aspect ObserverProtocol {
-
- @InterfaceAnnotation
- interface Observer {}
-
- @InterfaceAnnotation
- interface Subject {}
-
- @ITDFieldAnnotation
- private List<Observer> Subject.observers;
-
- @ITDMethodAnnotation
- public void Subject.addObserver(Observer o) {
- observers.add(o);
- }
-
- @ITDMethodAnnotation
- public void Subject.removeObserver(Observer o) {
- observers.remove(o);
- }
-
- @MethodAnnotation
- private void notifyObservers(Subject subject) {
- for(Observer o : subject.observers)
- notifyObserver(o,subject);
- }
-
- /**
- * Delegate to concrete sub-aspect the actual form of
- * notification for a given type of Observer.
- */
- @MethodAnnotation
- protected abstract void notifyObserver(Observer o, Subject s);
-
- /* no annotations on pointcuts */
- protected abstract pointcut observedEvent(Subject subject);
-
- @AdviceAnnotation
- after(Subject subject) returning : observedEvent(subject) {
- notifyObservers(subject);
- }
- }
- ]]></programlisting>
-
- <para>
- An annotation on an aspect will be inherited by sub-aspects, iff it has
- the <literal>@Inherited</literal> meta-annotation.
- </para>
-
- <para>
- AspectJ 5 supports a new XLint warning, "the pointcut associated with this
- advice does not match any join points". The warning is enabled by default and
- will be emitted by the compiler if the pointcut expression associated with an
- advice statement can be statically determined to not match any join points. The
- warning can be suppressed for an individual advice statement by using the
- <literal>@SuppressAjWarnings({"adviceDidNotMatch"})</literal> annotation. This works in
- the same way as the Java 5 SuppressWarnings annotation (See JLS 9.6.1.5), but has class file
- retention.
- </para>
-
- <programlisting><![CDATA[
- import org.aspectj.lang.annotation.SuppressAjWarnings;
-
- public aspect AnAspect {
-
- pointcut anInterfaceOperation() : execution(* AnInterface.*(..));
-
-
- @SuppressAjWarnings // may not match if there are no implementers of the interface...
- before() : anInterfaceOperation() {
- // do something...
- }
-
- @SuppressAjWarnings("adviceDidNotMatch") // alternate form
- after() returning : anInterfaceOperation() {
- // do something...
- }
- }
- ]]></programlisting>
-
-
- </sect1>
-
- <!-- ============================== -->
-
- <sect1 id="annotations-pointcuts-and-advice">
- <title>Join Point Matching based on Annotations</title>
-
- <para>
- This section discusses changes to type pattern and signature pattern matching in
- AspectJ 5 that support matching join points based on the presence or absence of
- annotations. We then discuss means of exposing annotation values within the body
- of advice.
- </para>
-
- <sect2 id="annotation-patterns" xreflabel="annotation-patterns">
- <title>Annotation Patterns</title>
-
- <para>
- For any kind of annotated element (type, method, constructor, package, etc.),
- an annotation pattern can be used to match against the set of annotations
- on the annotated element.An annotation pattern element has one of two basic
- forms:
- </para>
-
- <itemizedlist>
- <listitem>@<qualified-name>, for example, @Foo, or
- @org.xyz.Foo.</listitem>
- <listitem>@(<type-pattern>), for example, @(org.xyz..*), or
- @(Foo || Boo)</listitem>
- </itemizedlist>
-
- <para>These simple elements may be negated using <literal>!</literal>, and
- combined by simple concatentation. The pattern <literal>@Foo @Boo</literal>
- matches an annotated element that has both an annotation of type <literal>Foo</literal>
- and an annotation of type <literal>Boo</literal>.</para>
-
- <para>Some examples of annotation patterns follow:</para>
-
- <variablelist>
-
- <varlistentry>
- <term>@Immutable</term>
- <listitem>
- <para>
- Matches any annotated element which has an annotation of
- type <literal>Immutable</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>!@Persistent</term>
- <listitem>
- <para>
- Matches any annotated element which does not have an annotation of
- type <literal>Persistent</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@Foo @Goo</term>
- <listitem>
- <para>
- Matches any annotated element which has both an annotation of type <literal>Foo</literal> and
- an annotation of type <literal>Goo</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@(Foo || Goo)</term>
- <listitem>
- <para>
- Matches any annotated element which has either an annotation of a type matching
- the type pattern <literal>(Foo || Goo)</literal>.
- In other words, an annotated element with either an
- annotation of type <literal>Foo</literal> or
- an annotation of type <literal>Goo</literal> (or both). (The parenthesis are required in this example).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@(org.xyz..*)</term>
- <listitem>
- <para>
- Matches any annotated element which has either an annotation of a type matching
- the type pattern <literal>(org.xyz..*)</literal>.
- In other words, an annotated element with an annotation that is declared in the
- org.xyz package or a sub-package. (The parenthesis are required in this example).
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- <sect2 id="type-patterns" xreflabel="type-patterns">
- <title>Type Patterns</title>
-
- <para>AspectJ 1.5 extends type patterns to allow an optional <literal>AnnotationPattern</literal>
- prefix.</para>
-
- <programlisting><![CDATA[
- TypePattern := SimpleTypePattern |
- '!' TypePattern |
- '(' AnnotationPattern? TypePattern ')'
- TypePattern '&&' TypePattern |
- TypePattern '||' TypePattern
-
- SimpleTypePattern := DottedNamePattern '+'? '[]'*
-
- DottedNamePattern := FullyQualifiedName RestOfNamePattern? |
- '*' NotStarNamePattern?
-
- RestOfNamePattern := '..' DottedNamePattern |
- '*' NotStarNamePattern?
-
- NotStarNamePattern := FullyQualifiedName RestOfNamePattern? |
- '..' DottedNamePattern
-
- FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)*
- ]]></programlisting>
-
- <para>Note that in most cases when annotations are used as part of a type pattern,
- the parenthesis are required (as in <literal>(@Foo Hello+)</literal>). In
- some cases (such as a type pattern used within a <literal>within</literal> or
- <literal>handler</literal>
- pointcut expression), the parenthesis are optional:</para>
-
- <programlisting><![CDATA[
- OptionalParensTypePattern := AnnotationPattern? TypePattern
- ]]> </programlisting>
-
- <para>
- The following examples illustrate the use of annotations in type
- patterns:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>(@Immutable *)</term>
- <listitem>
- <para>
- Matches any type with an <literal>@Immutable</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>(!@Immutable *)</term>
- <listitem>
- <para>
- Matches any type which does not have an <literal>@Immutable</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term> (@Immutable (org.xyz.* || org.abc.*))</term>
- <listitem>
- <para>
- Matches any type in the <literal>org.xyz</literal> or <literal>org.abc</literal>
- packages with the <literal>@Immutable</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>((@Immutable Foo+) || Goo)</term>
- <listitem>
- <para>
- Matches a type <literal>Foo</literal> or any of its subtypes, which have the <literal>@Immutable</literal>
- annotation, or a type <literal>Goo</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>((@(Immutable || NonPersistent) org.xyz..*)</term>
- <listitem>
- <para>
- Matches any type in a package beginning with the prefix <literal>org.xyz</literal>,
- which has either the <literal>@Immutable</literal> annotation or the
- <literal>@NonPersistent</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>(@Immutable @NonPersistent org.xyz..*)</term>
- <listitem>
- <para>
- Matches any type in a package beginning with the prefix <literal>org.xyz</literal>,
- which has both an <literal>@Immutable</literal> annotation and an
- <literal>@NonPersistent</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term> (@(@Inherited *) org.xyz..*)</term>
- <listitem>
- <para>
- Matches any type in a package beginning with the prefix <literal>org.xyz</literal>,
- which has an inheritable annotation. The annotation pattern
- <literal>@(@Inherited *)</literal> matches any annotation of a type matching the
- type pattern <literal>@Inherited *</literal>, which in turn matches any type with the
- <literal>@Inherited</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- <sect2 id="signaturePatterns" xreflabel="Signature Patterns">
- <title>Signature Patterns</title>
-
- <sect3 id="fieldPatterns" xreflabel="Field Patterns">
- <title>Field Patterns</title>
-
- <para>A <literal>FieldPattern</literal> can optionally specify an annotation-matching
- pattern as the first element:</para>
-
- <programlisting><![CDATA[
- FieldPattern :=
- AnnotationPattern? FieldModifiersPattern?
- TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern
-
- FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern*
-
- FieldModifier := 'public' | 'private' | 'protected' | 'static' |
- 'transient' | 'final'
-
- DotOrDotDot := '.' | '..'
-
- SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)?
- ]]></programlisting>
-
- <para>
- If present, the <literal>AnnotationPattern</literal> restricts matches to fields with
- annotations that match the pattern. For example:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>@SensitiveData * *</term>
- <listitem>
- <para>
- Matches a field of any type and any name, that has an annotation of
- type <literal>@SensitiveData</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@SensitiveData List org.xyz..*.*</term>
- <listitem>
- <para>
- Matches a member field of a type in a package with prefix <literal>org.xzy</literal>,
- where the field is of type <literal>List</literal>, and has an annotation of type
- <literal>@SensitiveData</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>(@SensitiveData *) org.xyz..*.*</term>
- <listitem>
- <para>
- Matches a member field of a type in a package with prefix <literal>org.xzy</literal>,
- where the field is of a type which has a <literal>@SensitiveData</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@Foo (@Goo *) (@Hoo *).*</term>
- <listitem>
- <para>
- Matches a field with an annotation <literal>@Foo</literal>, of a type with an
- annotation <literal>@Goo</literal>, declared in a type with annotation
- <literal>@Hoo</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@Persisted @Classified * *</term>
- <listitem>
- <para>
- Matches a field with an annotation <literal>@Persisted</literal> and
- an annotation <literal>@Classified</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect3>
-
- <sect3 id="methodPatterns" xreflabel="Method Patterns">
- <title>Method and Constructor Patterns</title>
-
- <para>A <literal>MethodPattern</literal> can optionally specify an annotation-matching
- pattern as the first element.</para>
-
- <programlisting><![CDATA[
- MethodPattern :=
- AnnotationPattern? MethodModifiersPattern? TypePattern
- (TypePattern DotOrDotDot)? SimpleNamePattern
- '(' FormalsPattern ')'ThrowsPattern?
-
- MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern*
-
- MethodModifier := 'public' | 'private' | 'protected' | 'static' |
- 'synchronized' | 'final'
-
- FormalsPattern := '..' (',' FormalsPatternAfterDotDot)* |
- OptionalParensTypePattern (',' FormalsPattern)* |
- TypePattern '...'
-
- FormalsPatternAfterDotDot :=
- OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* |
- TypePattern '...'
-
- ThrowsPattern := 'throws' TypePatternList
-
- TypePatternList := TypePattern (',' TypePattern)*
- ]]></programlisting>
-
- <para>A <literal>ConstructorPattern</literal> has the form</para>
-
- <programlisting><![CDATA[
- ConstructorPattern :=
- AnnotationPattern? ConstructorModifiersPattern?
- (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')'
- ThrowsPattern?
-
- ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern*
-
- ConstructorModifier := 'public' | 'private' | 'protected'
- ]]></programlisting>
-
- <para>
- The optional <literal>AnnotationPattern</literal> at the beginning of a
- method or constructor pattern restricts matches to methods/constructors with
- annotations that match the pattern. For example:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>@Oneway * *(..)</term>
- <listitem>
- <para>
- Matches a method with any return type and any name, that has an annotation of
- type <literal>@Oneway</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>@Transaction * (@Persistent org.xyz..*).*(..)</term>
- <listitem>
- <para>
- Matches a method with the <literal>@Transaction</literal> annotation,
- declared in a type with the <literal>@Persistent</literal> annotation, and
- in a package beginning with the <literal>org.xyz</literal> prefix.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>* *.*(@Immutable *,..)</term>
- <listitem>
- <para>
- Matches any method taking at least one parameter, where the parameter
- type has an annotation <literal>@Immutable</literal>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- </sect3>
-
- </sect2>
-
- <sect2 id="example-pointcuts" xreflabel="example-pointcuts">
- <title>Example Pointcuts</title>
-
- <variablelist>
-
- <varlistentry>
- <term>within(@Secure *)</term>
- <listitem>
- <para>
- Matches any join point where the code executing is declared in a
- type with an <literal>@Secure</literal>
- annotation. The format of the <literal>within</literal> pointcut designator
- in AspectJ 5 is <literal>'within' '(' OptionalParensTypePattern ')'</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>staticinitialization(@Persistent *)</term>
- <listitem>
- <para>
- Matches the staticinitialization join point of any type with the
- <literal>@Persistent</literal> annotation. The format of the
- <literal>staticinitialization</literal> pointcut designator
- in AspectJ 5 is <literal>'staticinitialization' '(' OptionalParensTypePattern ')'</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>call(@Oneway * *(..))</term>
- <listitem>
- <para>
- Matches a call to a method with a <literal>@Oneway</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>execution(public (@Immutable *) org.xyz..*.*(..))</term>
- <listitem>
- <para>
- The execution of any public method in a package with prefix
- <literal>org.xyz</literal>, where the method returns an
- immutable result.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>set(@Cachable * *)</term>
- <listitem>
- <para>
- Matches the set of any cachable field.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>handler(!@Catastrophic *)</term>
- <listitem>
- <para>
- Matches the handler join point for the handling of any exception that is
- not <literal>Catastrophic</literal>. The format of the <literal>handler</literal>
- pointcut designator in AspectJ 5 is <literal>'handler' '(' OptionalParensTypePattern ')'</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- <sect2 id="runtime-type-matching-and-context-exposure" xreflabel="runtime-type-matching-and-context-exposure">
- <title>Runtime type matching and context exposure</title>
-
- <para>AspectJ 5 supports a set of "@" pointcut designators which
- can be used both to match based on the presence of an annotation at
- runtime, and to expose the annotation value as context in a pointcut or
- advice definition. These designators are <literal>@args, @this, @target,
- @within, @withincode</literal>, and <literal>@annotation</literal>
- </para>
-
- <para>It is a compilation error to attempt to match on an annotation type
- that does not have runtime retention using <literal>@this, @target</literal>
- or <literal>@args</literal>. It is a compilation error to attempt to use
- any of these designators to expose an annotation value that does not
- have runtime retention.</para>
-
- <para>
- The <literal>this()</literal>, <literal>target()</literal>, and
- <literal>args()</literal> pointcut designators allow matching based
- on the runtime type of an object, as opposed to the statically
- declared type. In AspectJ 5, these designators are supplemented
- with three new designators : <literal>@this()</literal> (read, "this
- annotation"), <literal>@target()</literal>, and <literal>@args()</literal>.
- </para>
-
- <para>
- Like their counterparts, these pointcut designators can be used
- both for join point matching, and to expose context. The format of
- these new designators is:
- </para>
-
- <programlisting><![CDATA[
- AtThis := '@this' '(' AnnotationOrIdentifer ')'
-
- AtTarget := '@target' '(' AnnotationOrIdentifier ')'
-
- AnnotationOrIdentifier := FullyQualifiedName | Identifier
-
- AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')'
-
- AnnotationsOrIdentifiersPattern :=
- '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? |
- AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* |
- '*' (',' AnnotationsOrIdentifiersPattern)*
-
- AnnotationsOrIdentifiersPatternAfterDotDot :=
- AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* |
- '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)*
- ]]></programlisting>
-
- <para>
- The forms of <literal>@this()</literal> and <literal>@target()</literal> that
- take a single annotation name are analogous to their counterparts that take
- a single type name. They match at join points where the object bound to
- <literal>this</literal> (or <literal>target</literal>, respectively) has an
- annotation of the specified type. For example:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>@this(Foo)</term>
- <listitem>
- <para>
- Matches any join point where the object currently bound to 'this'
- has an annotation of type <literal>Foo</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>call(* *(..)) && @target(Classified)</term>
- <listitem>
- <para>
- Matches a call to any object where the target of the call has
- a <literal>@Classified</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- <para>
- Annotations can be exposed as context in the body of advice by
- using the forms of <literal>@this(), @target()</literal> and
- <literal>@args()</literal> that use bound variables in the place
- of annotation names. For example:
- </para>
-
- <programlisting><![CDATA[
- pointcut callToClassifiedObject(Classified classificationInfo) :
- call(* *(..)) && @target(classificationInfo);
-
- pointcut txRequiredMethod(Tx transactionAnnotation) :
- execution(* *(..)) && @this(transactionAnnotation)
- && if(transactionAnnotation.policy() == TxPolicy.REQUIRED);
- ]]></programlisting>
-
- <para>
- The <literal>@args</literal> pointcut designator behaves as its <literal>args</literal>
- counterpart, matching join points based on number and position of arguments, and
- supporting the <literal>*</literal> wildcard and at most one <literal>..</literal>
- wildcard. An annotation at a given position in an <literal>@args</literal> expression
- indicates that the runtime type of the argument in that position at a join point must
- have an annotation of the indicated type. For example:
- </para>
-
- <programlisting><![CDATA[
- /**
- * matches any join point with at least one argument, and where the
- * type of the first argument has the @Classified annotation
- */
- pointcut classifiedArgument() : @args(Classified,..);
-
- /**
- * matches any join point with three arguments, where the third
- * argument has an annotation of type @Untrusted.
- */
- pointcut untrustedData(Untrusted untrustedDataSource) :
- @args(*,*,untrustedDataSource);
- ]]></programlisting>
-
- <para>In addition to accessing annotation information at runtime through context binding,
- access to <literal>AnnotatedElement</literal> information is also available
- reflectively with the body of advice through the <literal>thisJoinPoint</literal>,
- <literal>thisJoinPointStaticPart</literal>, and
- <literal>thisEnclosingJoinPointStaticPart</literal> variables. To access
- annotations on the arguments, or object bound to this or target at a join
- point you can use the following code fragments:</para>
-
- <programlisting><![CDATA[
- Annotation[] thisAnnotations = thisJoinPoint.getThis().getClass().getAnnotations();
- Annotation[] targetAnnotations = thisJoinPoint.getTarget().getClass().getAnnotations();
- Annotation[] firstParamAnnotations = thisJoinPoint.getArgs()[0].getClass().getAnnotations();
- ]]></programlisting>
-
- <para>
- The <literal>@within</literal> and <literal>@withincode</literal> pointcut designators
- match any join point where the executing code is defined within a type (<literal>@within</literal>),
- or a method/constructor (<literal>@withincode</literal>) that has an annotation of the specified
- type. The form of these designators is:
- </para>
-
- <programlisting><![CDATA[
- AtWithin := '@within' '(' AnnotationOrIdentifier ')'
- AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')'
- ]]></programlisting>
-
- <para>Some examples of using these designators follow:</para>
-
- <variablelist>
-
- <varlistentry>
- <term>@within(Foo)</term>
- <listitem>
- <para>
- Matches any join point where the executing code is defined
- within a type which has an annotation of type <literal>Foo</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>pointcut insideCriticalMethod(Critical c) :
- @withincode(c);</term>
- <listitem>
- <para>
- Matches any join point where the executing code is defined
- in a method or constructor which has an annotation of type <literal>@Critical</literal>,
- and exposes the value of the annotation in the parameter
- <literal>c</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- <para>The <literal>@annotation</literal> pointcut designator matches any
- join point where the <emphasis>subject</emphasis> of the join point has
- an annotation of the given type. Like the other @pcds, it can also be
- used for context exposure.</para>
-
- <programlisting><![CDATA[
- AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')'
- ]]></programlisting>
-
- <para>The subject of a join point is defined in the table in chapter one of
- this guide.</para>
-
- <para>
- Access to annotation information on members at a matched join point is also available
- through the <literal>getSignature</literal> method of the <literal>JoinPoint</literal>
- and <literal>JoinPoint.StaticPart</literal> interfaces. The <literal>Signature</literal>
- interfaces are extended with additional operations that provide access to the
- <literal>java.lang.reflect</literal> <literal>Method, Field</literal> and
- <literal>Constructor</literal> objects on which annnotations can be queried. The following fragment
- illustrates an example use of this interface to access annotation information.
- </para>
-
- <programlisting><![CDATA[
- Signature sig = thisJoinPointStaticPart.getSignature();
- AnnotatedElement declaringTypeAnnotationInfo = sig.getDeclaringType();
- if (sig instanceof MethodSignature) {
- // this must be a call or execution join point
- Method method = ((MethodSignature)sig).getMethod();
- }
- ]]></programlisting>
-
- <para>
- <emphasis>Note again that it would be nicer to add the method getAnnotationInfo
- directly to MemberSignature, but this would once more couple the runtime library
- to Java 5.</emphasis>
- </para>
-
- <para>
- The <literal>@this,@target</literal> and <literal>@args</literal>
- pointcut designators can only be used to match against annotations
- that have runtime retention. The <literal>@within, @withincode</literal>
- and <literal>@annotation</literal> pointcut designators can only be used
- to match against annotations that have at least class-file retention, and
- if used in the binding form the annotation must have runtime retention.
- </para>
-
- </sect2>
-
-
- <sect2 id="package-and-parameter-annotations" xreflabel="package-and-parameter-annotations">
- <title>Package and Parameter Annotations</title>
-
- <para>
- <emphasis>Matching on package annotations is not supported in AspectJ. Support for
- this capability may be considered in a future release.</emphasis>
-
- </para>
-
- <para>
- Parameter annotation matching is being added in AspectJ1.6.
- Initially only matching is supported but binding will be
- implemented at some point. Whether the annotation specified in a pointcut should be
- considered to be an annotation on the parameter type or an annotation on the parameter
- itself is determined through the use of parentheses around the parameter type.
-
- Consider the following:
- </para>
-
-
- <programlisting><![CDATA[
- @SomeAnnotation
- class AnnotatedType {}
-
- class C {
- public void foo(AnnotatedType a) {}
- public void goo(@SomeAnnotation String s) {}
- }
- ]]></programlisting>
-
- <para>
- The method foo has a parameter of an annotated type, and can be matched by this pointcut:
- </para>
- <programlisting><![CDATA[
- pointcut p(): execution(* *(@SomeAnnotation *));
- ]]></programlisting>
- <para>
- When there is a single annotation specified like this, it is considered to be part of the type
- pattern in the match against the parameter: 'a parameter of any type that has the annotation @SomeAnnotation'.
- </para>
- <para>
- To match the parameter annotation case, the method goo, this is the pointcut:
- </para>
- <programlisting><![CDATA[
- pointcut p(): execution(* *(@SomeAnnotation (*)));
- ]]></programlisting>
- <para>
- The use of parentheses around the wildcard is effectively indicating that the annotation should be considered
- separately to the type pattern for the parameter type: 'a parameter of any type that has a parameter annotation of
- @SomeAnnotation'.
- </para>
- <para>
- To match when there is a parameter annotation and an annotation on the type as well:
- </para>
- <programlisting><![CDATA[
- pointcut p(): execution(* *(@SomeAnnotation (@SomeOtherAnnotation *)));
- ]]></programlisting>
- <para>
- The parentheses are grouping @SomeOtherAnnotation with the * to form the type pattern for the parameter, then
- the type @SomeAnnotation will be treated as a parameter annotation pattern.
- </para>
-
- <!-- @withinpackage ??? -->
-
- <!--
- <para>
- Java 5 allows both packages and parameters to be annotated. To allow matching on package and parameter annotations,
- AspectJ 5 introduces the <literal>@package</literal> and <literal>@parameters</literal> pointcut designators.
- </para>
-
- <programlisting><![CDATA[
- PackageAnnotationPointcut := '@package' '(' AnnotationPattern ')'
- ]]></programlisting>
-
- <para>The <literal>@package</literal> pointcut matches any join point
- occuring within the scope of a package with
- annotations matching the giving <literal>AnnotationPattern</literal>. For
- example:
- </para>
-
- <programlisting><![CDATA[
- @package(@Model)
- ]]></programlisting>
-
- <para>
- Matches any join point occuring within the scope of a package with the
- <literal>@Model</literal> annotation.
- </para>
-
- <para>
- <emphasis>
- Note: we added @package as a result of a conscious decision not to allow the
- specification of package annotation patterns within a general TypePattern. A
- consequence of this decision is that we lose the ability to say the following
- things: "a call to a method defined in a type in a package with annotations
- matching..." ; "the set of a field defined in a type in a package with annotations
- matching..." ; "the get of a field defined in a type in a package with annotations
- matching...". As well as the package of the target at these join points, there is
- also the package of the runtime type of the target (call/target difference). So
- there are at least three possible sets of package annotations you could theoretically
- want to match on at a call, get, or set join point. We have chosen to provide the
- means to express the simplest of these, and could consider extending the language
- to allow for the others in the future when we better understanding how users will
- really use both package annotations and these features.
- </emphasis>
- </para>
-
- <para>
- The <literal>@parameter</literal> pointcut designator acts in a similar manner to
- <literal>args</literal> in that it matches based on number and position of arguments
- at a join point (and supports the same wildcard options of <literal>*</literal> and
- <literal>..</literal>.
- </para>
-
- <programlisting><![CDATA[
- ParamsAnnotationPointcut := '@parameters' '(' ParamsAnnotationPattern ')'
-
- ParamsAnnotationPattern := AnnotationPattern (',' ParamsAnnotationPattern)? |
- '*' (',' ParamsAnnotationPattern)? |
- '..' (',' SingleParamsAnnotationPattern)*
-
- SingleParamsAnnotationPattern := AnnotationPattern (',' SingleParamsAnnotationPattern)? |
- '*' (',' SingleParamsAnnotationPattern)?
- ]]></programlisting>
-
- <para>The <literal>*</literal> wildcard matches a single parameter regardless of its annotations.
- The <literal>..</literal> wildcard matches zero or more parameters with any annotations. An
- annotation pattern in a given parameter position matches a parameter in that position with annotations
- matching the given annotation pattern. For example, the method signature</para>
-
- <programlisting><![CDATA[
- public void foo(@Immutable int i, String s, @Cached Object o);
- ]]></programlisting>
-
- <para>Is matched by:</para>
- <programlisting><![CDATA[@parameters(@Immutable, *, @Cached);]]></programlisting>
- <para>and,</para>
- <programlisting><![CDATA[@parameters(..,@Cached);]]></programlisting>
- <para>and,</para>
- <programlisting><![CDATA[@parameters(@Immutable, *, *);]]></programlisting>
-
- <para>It is not matched by:</para>
- <programlisting><![CDATA[@parameters(@Immutable, *);]]></programlisting>
- <para>or,</para>
- <programlisting><![CDATA[@parameters(*,@Immutable);]]></programlisting>
- <para>or,</para>
- <programlisting><![CDATA[@parameters(*, int, @Cached);]]></programlisting>
-
- <para>
- This last example will result in a compilation error since <literal>int</literal> is not a
- valid annotation pattern.
- </para>
- -->
-
- </sect2>
-
- <sect2 id="annotation-inheritance-and-pointcut-matching" xreflabel="annotation-inheritance-and-pointcut-matching">
- <title>Annotation Inheritance and pointcut matching</title>
-
- <para>
- According to the Java 5 specification, non-type annotations are not
- inherited, and annotations on types are only inherited if they have the
- <literal>@Inherited</literal> meta-annotation.
-
- Given the following program:
- </para>
-
- <programlisting><![CDATA[
- class C1 {
- @SomeAnnotation
- public void aMethod() {...}
- }
-
- class C2 extends C1 {
- public void aMethod() {...}
- }
-
- class Main {
- public static void main(String[] args) {
- C1 c1 = new C1();
- C2 c2 = new C2();
- c1.aMethod();
- c2.aMethod();
- }
- }
-
- aspect X {
- pointcut annotatedC2MethodCall() :
- call(@SomeAnnotation * C2.aMethod());
-
- pointcut annotatedMethodCall() :
- call(@SomeAnnotation * aMethod());
- }
- ]]></programlisting>
-
- <para>
- The pointcut <literal>annotatedC2MethodCall</literal> will not match anything
- since the definition of <literal>aMethod</literal> in <literal>C2</literal>
- does not have the annotation.
- </para>
-
- <para>
- The pointcut <literal>annotatedMethodCall</literal> matches
- <literal>c1.aMethod()</literal> but not <literal>c2.aMethod()</literal>. The call
- to <literal>c2.aMethod</literal> is not matched because join point matching for
- modifiers (the visibility modifiers, annotations, and throws clause) is based on
- the subject of the join point (the method actually being called).
- </para>
-
- </sect2>
-
- <sect2 id="matchingOnAnnotationValues" xreflabel="matchingOnAnnotationValues">
- <title>Matching based on annotation values</title>
- <para>
- The <literal>if</literal> pointcut designator can be used to write pointcuts
- that match based on the values annotation members. For example:
- </para>
-
- <programlisting><![CDATA[
- pointcut txRequiredMethod(Tx transactionAnnotation) :
- execution(* *(..)) && @this(transactionAnnotation)
- && if(transactionAnnotation.policy() == TxPolicy.REQUIRED);
- ]]></programlisting>
-
- </sect2>
-
- </sect1>
-
- <!-- ============================== -->
-
- <sect1 id="annotations-decp">
- <title>Using Annotations with declare statements</title>
-
- <sect2 id="declare-error-and-declare-warning" xreflabel="declare-error-and-declare-warning">
- <title>Declare error and declare warning</title>
-
- <para>
- Since pointcut expressions in AspectJ 5 support join point matching based
- on annotations, this facility can be exploited when writing
- <literal>declare warning</literal> and <literal>declare error</literal>
- statements. For example:
- </para>
-
- <programlisting><![CDATA[
- declare warning : withincode(@PerformanceCritical * *(..)) &&
- call(@ExpensiveOperation * *(..))
- : "Expensive operation called from within performance critical section";
- ]]></programlisting>
-
- <programlisting><![CDATA[
- declare error : call(* org.xyz.model.*.*(..)) &&
- !@within(Trusted)
- : "Untrusted code should not call the model classes directly";
- ]]></programlisting>
-
- </sect2>
-
-
- <sect2 id="declare-parents" xreflabel="declare-parents">
- <title>declare parents</title>
-
- <para>
- The general form of a <literal>declare parents</literal> statement is:
- </para>
-
- <programlisting><![CDATA[
- declare parents : TypePattern extends Type;
- declare parents : TypePattern implements TypeList;
- ]]></programlisting>
-
- <para>
- Since AspectJ 5 supports annotations as part of a type pattern
- specification, it is now possible to match types based on the presence
- of annotations <emphasis>with either class-file or runtime retention</emphasis>.
- For example:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>declare parents : (@Secured *) implements SecuredObject;</term>
- <listitem>
- <para>
- All types with the <literal>@Secured</literal> annotation
- implement the <literal>SecuredObject</literal> inteface.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>declare parents : (@Secured BankAccount+) implements SecuredObject;</term>
- <listitem>
- <para>
- The subset of types drawn from the <literal>BankAccount</literal> type and any subtype of
- <literal>BankAccount</literal>, where the
- <literal>@Secured</literal> annotation is present, implement the
- <literal>SecuredObject</literal> interface.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- <para>An annotation type may not be used as the target of a declare parents
- statement. If an annotation type is named explicitly as the target of a
- declare parents statement, a compilation error will result. If an annotation
- type is matched by a non-explicit type pattern used in a declare parents
- statement it will be ignored (and an XLint warning issued).</para>
-
- </sect2>
-
- <sect2 id="declare-precedence" xreflabel="declare-precedence">
- <title>declare precedence</title>
-
- <para>
- The general form of a declare precedence statement is:
- </para>
-
- <programlisting><![CDATA[
- declare precedence : TypePatList;
- ]]></programlisting>
-
- <para>
- AspectJ 5 allows the type patterns in the list to include annotation information
- as part of the pattern specification. For example:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>declare precedence : (@Security *),*;</term>
- <listitem>
- <para>
- All aspects with the <literal>@Security</literal> annotation
- take precedence over any other aspects in the system. (Or, more
- informally, all security-related aspects take precedence).
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- </sect1>
-
- <!-- ============================== -->
-
- <sect1 id="annotations-declare">
- <title>Declare Annotation</title>
-
- <para>AspectJ 5 supports a new kind of declare statement, <literal>declare annotation</literal>.
- This takes different forms according to the recipient of the annotation:
- <literal>declare @type</literal> for types, <literal>declare @method</literal> for methods,
- <literal>declare @constructor</literal> for constructors, and <literal>declare @field</literal>
- for fields. <literal>declare @package</literal> may be supported in a future release.
- </para>
-
- <para>The general form is:</para>
-
- <programlisting><![CDATA[
- declare @<kind> : ElementPattern : Annotation ;
- ]]></programlisting>
-
- <para>Where annotation is a regular annotation expression as defined in the Java 5 language. If the annotation has
- the <literal>@Target</literal> meta-annotation, then the elements matched by <literal>ElementPattern</literal>
- must be of the kind specified by the <literal>@Target</literal> annotation.</para>
-
- <para><literal>ElementPattern</literal> is defined as follows:</para>
-
- <programlisting><![CDATA[
- ElementPattern := TypePattern |
- MethodPattern |
- ConstructorPattern |
- FieldPattern
- ]]></programlisting>
-
- <para>The following examples illustrate the use of <literal>declare annotation</literal>.</para>
-
- <variablelist>
-
- <varlistentry>
- <term>declare @type : org.xyz.model..* : @BusinessDomain ;</term>
- <listitem>
- <para>
- All types defined in a package with the prefix <literal>org.xyz.model</literal>
- have the <literal>@BusinessDomain</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>declare @method : public * BankAccount+.*(..) : @Secured(role="supervisor")</term>
- <listitem>
- <para>
- All public methods in <literal>BankAccount</literal> and its subtypes have the
- annotation <literal>@Secured(role="supervisor")</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>declare @constructor : BankAccount+.new(..) : @Secured(role="supervisor")</term>
- <listitem>
- <para>
- All constructors in <literal>BankAccount</literal> and its subtypes have the
- annotation <literal>@Secured(role="supervisor")</literal>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>declare @field : * DAO+.* : @Persisted;</term>
- <listitem>
- <para>
- All fields defined in <literal>DAO</literal> or its subtypes have the
- <literal>@Persisted</literal> annotation.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect1>
-
- <sect1 id="annotations-itds">
- <title>Inter-type Declarations</title>
-
- <para>An annotation type may not be the target of an inter-type declaration.</para>
- </sect1>
-
- </chapter>
-
|