1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
|
<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);
and,
@parameters(..,@Cached);
and,
@parameters(@Immutable, *, *);
]]></programlisting>
<para>
It is not matched by:
</para>
<programlisting><![CDATA[
@parameters(@Immutable, *);
or,
@parameters(*,@Immutable);
or,
@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>
|