You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

annotations.adoc 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. = Annotations
  2. [[annotations-inJava5]]
  3. == Annotations in Java 5
  4. This section provides the essential information about annotations in
  5. Java 5 needed to understand how annotations are treated in AspectJ 5.
  6. For a full introduction to annotations in Java, please see the
  7. documentation for the Java 5 SDK.
  8. === Using Annotations
  9. Java 5 introduces _annotation types_ which can be used to express
  10. metadata relating to program members in the form of _annotations_.
  11. Annotations in Java 5 can be applied to package and type declarations
  12. (classes, interfaces, enums, and annotations), constructors, methods,
  13. fields, parameters, and variables. Annotations are specified in the
  14. program source by using the `@` symbol. For example, the following piece
  15. of code uses the `@Deprecated` annotation to indicate that the
  16. `obsoleteMethod()` has been deprecated:
  17. [source, java]
  18. ....
  19. @Deprecated
  20. public void obsoleteMethod() { ... }
  21. ....
  22. Annotations may be _marker annotations_, _single-valued annotations_, or
  23. _multi-valued annotations_. Annotation types with no members or that
  24. provide default values for all members may be used simply as marker
  25. annotations, as in the deprecation example above. Single-value
  26. annotation types have a single member, and the annotation may be written
  27. in one of two equivalent forms:
  28. [source, java]
  29. ....
  30. @SuppressWarnings({"unchecked"})
  31. public void someMethod() {...}
  32. ....
  33. or
  34. [source, java]
  35. ....
  36. @SuppressWarnings(value={"unchecked"})
  37. public void someMethod() {...}
  38. ....
  39. Multi-value annotations must use the `member-name=value
  40. ` syntax to specify annotation values. For example:
  41. [source, java]
  42. ....
  43. @Authenticated(role="supervisor",clearanceLevel=5)
  44. public void someMethod() {...}
  45. ....
  46. === Retention Policies
  47. Annotations can have one of three retention policies:
  48. Source-file retention::
  49. Annotations with source-file retention are read by the compiler during
  50. the compilation process, but are not rendered in the generated `.class` files.
  51. Class-file retention::
  52. This is the default retention policy. Annotations with class-file
  53. retention are read by the compiler and also retained in the generated `.class` files.
  54. Runtime retention::
  55. Annotations with runtime retention are read by the compiler, retained
  56. in the generated `.class` files, and also made available at
  57. runtime.
  58. Local variable annotations are not retained in class files (or at
  59. runtime) regardless of the retention policy set on the annotation type.
  60. See JLS 9.6.1.2.
  61. === Accessing Annotations at Runtime
  62. Java 5 supports a new interface, `java.lang.reflect.AnnotatedElement`,
  63. that is implemented by the reflection classes in Java (`Class`,
  64. `Constructor`, `Field`, `Method`, and `Package`). This interface gives
  65. you access to annotations _that have runtime retention_ via the
  66. `getAnnotation`, `getAnnotations`, and `isAnnotationPresent`. Because
  67. annotation types are just regular Java classes, the annotations returned
  68. by these methods can be queried just like any regular Java object.
  69. === Annotation Inheritance
  70. It is important to understand the rules relating to inheritance of
  71. annotations, as these have a bearing on join point matching based on the
  72. presence or absence of annotations.
  73. By default annotations are _not_ inherited. Given the following program
  74. [source, java]
  75. ....
  76. @MyAnnotation
  77. class Super {
  78. @Oneway public void foo() {}
  79. }
  80. class Sub extends Super {
  81. public void foo() {}
  82. }
  83. ....
  84. Then `Sub` _does not_ have the `MyAnnotation` annotation, and
  85. `Sub.foo()` is not an `@Oneway` method, despite the fact that it
  86. overrides `Super.foo()` which is.
  87. If an annotation type has the meta-annotation `@Inherited` then an
  88. annotation of that type on a _class_ will cause the annotation to be
  89. inherited by sub-classes. So, in the example above, if the
  90. `MyAnnotation` type had the `@Inherited` attribute, then `Sub` would
  91. have the `MyAnnotation` annotation.
  92. `@Inherited` annotations are not inherited when used to annotate
  93. anything other than a type. A type that implements one or more
  94. interfaces never inherits any annotations from the interfaces it
  95. implements.
  96. [[annotations-aspectmembers]]
  97. == Annotating Aspects
  98. AspectJ 5 supports annotations on aspects, and on method, field,
  99. constructor, advice, and inter-type declarations within aspects. Method
  100. and advice parameters may also be annotated. Annotations are not
  101. permitted on pointcut declarations or on `declare` statements.
  102. The following example illustrates the use of annotations in aspects:
  103. [source, java]
  104. ....
  105. @AspectAnnotation
  106. public abstract aspect ObserverProtocol {
  107. @InterfaceAnnotation
  108. interface Observer {}
  109. @InterfaceAnnotation
  110. interface Subject {}
  111. @ITDFieldAnnotation
  112. private List<Observer> Subject.observers;
  113. @ITDMethodAnnotation
  114. public void Subject.addObserver(Observer o) {
  115. observers.add(o);
  116. }
  117. @ITDMethodAnnotation
  118. public void Subject.removeObserver(Observer o) {
  119. observers.remove(o);
  120. }
  121. @MethodAnnotation
  122. private void notifyObservers(Subject subject) {
  123. for(Observer o : subject.observers)
  124. notifyObserver(o,subject);
  125. }
  126. /**
  127. * Delegate to concrete sub-aspect the actual form of
  128. * notification for a given type of Observer.
  129. */
  130. @MethodAnnotation
  131. protected abstract void notifyObserver(Observer o, Subject s);
  132. /* no annotations on pointcuts */
  133. protected abstract pointcut observedEvent(Subject subject);
  134. @AdviceAnnotation
  135. after(Subject subject) returning : observedEvent(subject) {
  136. notifyObservers(subject);
  137. }
  138. }
  139. ....
  140. An annotation on an aspect will be inherited by sub-aspects, iff it has
  141. the `@Inherited` meta-annotation.
  142. AspectJ 5 supports a new XLint warning, "the pointcut associated with
  143. this advice does not match any join points". The warning is enabled by
  144. default and will be emitted by the compiler if the pointcut expression
  145. associated with an advice statement can be statically determined to not
  146. match any join points. The warning can be suppressed for an individual
  147. advice statement by using the
  148. `@SuppressAjWarnings({"adviceDidNotMatch"})` annotation. This works in
  149. the same way as the Java 5 SuppressWarnings annotation (See JLS
  150. 9.6.1.5), but has class file retention.
  151. [source, java]
  152. ....
  153. import org.aspectj.lang.annotation.SuppressAjWarnings;
  154. public aspect AnAspect {
  155. pointcut anInterfaceOperation() : execution(* AnInterface.*(..));
  156. @SuppressAjWarnings // may not match if there are no implementers of the interface...
  157. before() : anInterfaceOperation() {
  158. // do something...
  159. }
  160. @SuppressAjWarnings("adviceDidNotMatch") // alternate form
  161. after() returning : anInterfaceOperation() {
  162. // do something...
  163. }
  164. }
  165. ....
  166. [[annotations-pointcuts-and-advice]]
  167. == Join Point Matching based on Annotations
  168. This section discusses changes to type pattern and signature pattern
  169. matching in AspectJ 5 that support matching join points based on the
  170. presence or absence of annotations. We then discuss means of exposing
  171. annotation values within the body of advice.
  172. === Annotation Patterns
  173. For any kind of annotated element (type, method, constructor, package,
  174. etc.), an annotation pattern can be used to match against the set of
  175. annotations on the annotated element.An annotation pattern element has
  176. one of two basic forms:
  177. * `@<qualified-name>`, for example, `@Foo`, or `@org.xyz.Foo`.
  178. * `@(<type-pattern>)`, for example, `@(org.xyz..*)`, or `@(Foo || Boo)`
  179. These simple elements may be negated using `!`, and combined by simple
  180. concatentation. The pattern `@Foo @Boo` matches an annotated element
  181. that has both an annotation of type `Foo` and an annotation of type
  182. `Boo`.
  183. Some examples of annotation patterns follow:
  184. `@Immutable`::
  185. Matches any annotated element which has an annotation of type
  186. `Immutable`.
  187. `!@Persistent`::
  188. Matches any annotated element which does not have an annotation of
  189. type `Persistent`.
  190. `@Foo @Goo`::
  191. Matches any annotated element which has both an annotation of type
  192. `Foo` and an annotation of type `Goo`.
  193. `@(Foo || Goo)`::
  194. Matches any annotated element which has either an annotation of a type
  195. matching the type pattern `(Foo || Goo)`. In other words, an annotated
  196. element with either an annotation of type `Foo` or an annotation of
  197. type `Goo` (or both). (The parenthesis are required in this example).
  198. `@(org.xyz..*)`::
  199. Matches any annotated element which has either an annotation of a type
  200. matching the type pattern `(org.xyz..*)`. In other words, an annotated
  201. element with an annotation that is declared in the org.xyz package or
  202. a sub-package. (The parenthesis are required in this example).
  203. === Type Patterns
  204. AspectJ 1.5 extends type patterns to allow an optional
  205. `AnnotationPattern` prefix.
  206. [source, text]
  207. ....
  208. TypePattern := SimpleTypePattern |
  209. '!' TypePattern |
  210. '(' AnnotationPattern? TypePattern ')'
  211. TypePattern '&&' TypePattern |
  212. TypePattern '||' TypePattern
  213. SimpleTypePattern := DottedNamePattern '+'? '[]'*
  214. DottedNamePattern := FullyQualifiedName RestOfNamePattern? |
  215. '*' NotStarNamePattern?
  216. RestOfNamePattern := '..' DottedNamePattern |
  217. '*' NotStarNamePattern?
  218. NotStarNamePattern := FullyQualifiedName RestOfNamePattern? |
  219. '..' DottedNamePattern
  220. FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)*
  221. ....
  222. Note that in most cases when annotations are used as part of a type
  223. pattern, the parenthesis are required (as in `(@Foo Hello+)`). In some
  224. cases (such as a type pattern used within a `within` or `handler`
  225. pointcut expression), the parenthesis are optional:
  226. [source, text]
  227. ....
  228. OptionalParensTypePattern := AnnotationPattern? TypePattern
  229. ....
  230. The following examples illustrate the use of annotations in type
  231. patterns:
  232. `(@Immutable *)`::
  233. Matches any type with an `@Immutable` annotation.
  234. `(!@Immutable *)`::
  235. Matches any type which does not have an `@Immutable` annotation.
  236. `(@Immutable (org.xyz.* || org.abc.*))`::
  237. Matches any type in the `org.xyz` or `org.abc` packages with the
  238. `@Immutable` annotation.
  239. `((@Immutable Foo+) || Goo)`::
  240. Matches a type `Foo` or any of its subtypes, which have the
  241. `@Immutable` annotation, or a type `Goo`.
  242. `((@(Immutable || NonPersistent) org.xyz..*)`::
  243. Matches any type in a package beginning with the prefix `org.xyz`,
  244. which has either the `@Immutable` annotation or the `@NonPersistent`
  245. annotation.
  246. `(@Immutable @NonPersistent org.xyz..*)`::
  247. Matches any type in a package beginning with the prefix `org.xyz`,
  248. which has both an `@Immutable` annotation and an `@NonPersistent`
  249. annotation.
  250. `(@(@Inherited *) org.xyz..*)`::
  251. Matches any type in a package beginning with the prefix `org.xyz`,
  252. which has an inheritable annotation. The annotation pattern
  253. `@(@Inherited *)` matches any annotation of a type matching the type
  254. pattern `@Inherited *`, which in turn matches any type with the
  255. `@Inherited` annotation.
  256. [[signaturePatterns]]
  257. === Signature Patterns
  258. [[fieldPatterns]]
  259. ==== Field Patterns
  260. A `FieldPattern` can optionally specify an annotation-matching pattern
  261. as the first element:
  262. [source, text]
  263. ....
  264. FieldPattern :=
  265. AnnotationPattern? FieldModifiersPattern?
  266. TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern
  267. FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern*
  268. FieldModifier := 'public' | 'private' | 'protected' | 'static' |
  269. 'transient' | 'final'
  270. DotOrDotDot := '.' | '..'
  271. SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)?
  272. ....
  273. If present, the `AnnotationPattern` restricts matches to fields with
  274. annotations that match the pattern. For example:
  275. `@SensitiveData * *`::
  276. Matches a field of any type and any name, that has an annotation of
  277. type `@SensitiveData`
  278. `@SensitiveData List org.xyz..*.*`::
  279. Matches a member field of a type in a package with prefix `org.xzy`,
  280. where the field is of type `List`, and has an annotation of type
  281. `@SensitiveData`
  282. `(@SensitiveData *) org.xyz..*.*`::
  283. Matches a member field of a type in a package with prefix `org.xzy`,
  284. where the field is of a type which has a `@SensitiveData` annotation.
  285. `@Foo (@Goo *) (@Hoo *).*`::
  286. Matches a field with an annotation `@Foo`, of a type with an
  287. annotation `@Goo`, declared in a type with annotation `@Hoo`.
  288. `@Persisted @Classified * *`::
  289. Matches a field with an annotation `@Persisted` and an annotation
  290. `@Classified`.
  291. [[methodPatterns]]
  292. ==== Method and Constructor Patterns
  293. A `MethodPattern` can optionally specify an annotation-matching pattern
  294. as the first element.
  295. [source, text]
  296. ....
  297. MethodPattern :=
  298. AnnotationPattern? MethodModifiersPattern? TypePattern
  299. (TypePattern DotOrDotDot)? SimpleNamePattern
  300. '(' FormalsPattern ')'ThrowsPattern?
  301. MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern*
  302. MethodModifier := 'public' | 'private' | 'protected' | 'static' |
  303. 'synchronized' | 'final'
  304. FormalsPattern := '..' (',' FormalsPatternAfterDotDot)* |
  305. OptionalParensTypePattern (',' FormalsPattern)* |
  306. TypePattern '...'
  307. FormalsPatternAfterDotDot :=
  308. OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* |
  309. TypePattern '...'
  310. ThrowsPattern := 'throws' TypePatternList
  311. TypePatternList := TypePattern (',' TypePattern)*
  312. ....
  313. A `ConstructorPattern` has the form
  314. [source, text]
  315. ....
  316. ConstructorPattern :=
  317. AnnotationPattern? ConstructorModifiersPattern?
  318. (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')'
  319. ThrowsPattern?
  320. ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern*
  321. ConstructorModifier := 'public' | 'private' | 'protected'
  322. ....
  323. The optional `AnnotationPattern` at the beginning of a method or
  324. constructor pattern restricts matches to methods/constructors with
  325. annotations that match the pattern. For example:
  326. `@Oneway * *(..)`::
  327. Matches a method with any return type and any name, that has an
  328. annotation of type `@Oneway`.
  329. `@Transaction * (@Persistent org.xyz..*).*(..)`::
  330. Matches a method with the `@Transaction` annotation, declared in a
  331. type with the `@Persistent` annotation, and in a package beginning
  332. with the `org.xyz` prefix.
  333. `* *.*(@Immutable *,..)`::
  334. Matches any method taking at least one parameter, where the parameter
  335. type has an annotation `@Immutable`.
  336. === Example Pointcuts
  337. `within(@Secure *)`::
  338. Matches any join point where the code executing is declared in a type
  339. with an `@Secure` annotation. The format of the `within` pointcut
  340. designator in AspectJ 5 is
  341. `'within' '(' OptionalParensTypePattern ')'`.
  342. `staticinitialization(@Persistent *)`::
  343. Matches the staticinitialization join point of any type with the
  344. `@Persistent` annotation. The format of the `staticinitialization`
  345. pointcut designator in AspectJ 5 is
  346. `'staticinitialization' '(' OptionalParensTypePattern ')'`.
  347. `call(@Oneway * *(..))`::
  348. Matches a call to a method with a `@Oneway` annotation.
  349. `execution(public (@Immutable *) org.xyz..*.*(..))`::
  350. The execution of any public method in a package with prefix `org.xyz`,
  351. where the method returns an immutable result.
  352. `set(@Cachable * *)`::
  353. Matches the set of any cachable field.
  354. `handler(!@Catastrophic *)`::
  355. Matches the handler join point for the handling of any exception that
  356. is not `Catastrophic`. The format of the `handler` pointcut designator
  357. in AspectJ 5 is `'handler' '(' OptionalParensTypePattern ')'`.
  358. === Runtime type matching and context exposure
  359. AspectJ 5 supports a set of "@" pointcut designators which can be used
  360. both to match based on the presence of an annotation at runtime, and to
  361. expose the annotation value as context in a pointcut or advice
  362. definition. These designators are `@args, @this, @target,
  363. @within, @withincode`, and `@annotation`
  364. It is a compilation error to attempt to match on an annotation type that
  365. does not have runtime retention using `@this, @target` or `@args`. It is
  366. a compilation error to attempt to use any of these designators to expose
  367. an annotation value that does not have runtime retention.
  368. The `this()`, `target()`, and `args()` pointcut designators allow
  369. matching based on the runtime type of an object, as opposed to the
  370. statically declared type. In AspectJ 5, these designators are
  371. supplemented with three new designators : `@this()` (read, "this
  372. annotation"), `@target()`, and `@args()`.
  373. Like their counterparts, these pointcut designators can be used both for
  374. join point matching, and to expose context. The format of these new
  375. designators is:
  376. [source, text]
  377. ....
  378. AtThis := '@this' '(' AnnotationOrIdentifer ')'
  379. AtTarget := '@target' '(' AnnotationOrIdentifier ')'
  380. AnnotationOrIdentifier := FullyQualifiedName | Identifier
  381. AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')'
  382. AnnotationsOrIdentifiersPattern :=
  383. '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? |
  384. AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* |
  385. '*' (',' AnnotationsOrIdentifiersPattern)*
  386. AnnotationsOrIdentifiersPatternAfterDotDot :=
  387. AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* |
  388. '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)*
  389. ....
  390. The forms of `@this()` and `@target()` that take a single annotation
  391. name are analogous to their counterparts that take a single type name.
  392. They match at join points where the object bound to `this` (or `target`,
  393. respectively) has an annotation of the specified type. For example:
  394. `@this(Foo)`::
  395. Matches any join point where the object currently bound to 'this' has
  396. an annotation of type `Foo`.
  397. `call(* *(..)) && @target(Classified)`::
  398. Matches a call to any object where the target of the call has a
  399. `@Classified` annotation.
  400. Annotations can be exposed as context in the body of advice by using the
  401. forms of `@this(), @target()` and `@args()` that use bound variables in
  402. the place of annotation names. For example:
  403. [source, java]
  404. ....
  405. pointcut callToClassifiedObject(Classified classificationInfo) :
  406. call(* *(..)) && @target(classificationInfo);
  407. pointcut txRequiredMethod(Tx transactionAnnotation) :
  408. execution(* *(..)) && @this(transactionAnnotation)
  409. && if(transactionAnnotation.policy() == TxPolicy.REQUIRED);
  410. ....
  411. The `@args` pointcut designator behaves as its `args` counterpart,
  412. matching join points based on number and position of arguments, and
  413. supporting the `*` wildcard and at most one `..` wildcard. An annotation
  414. at a given position in an `@args` expression indicates that the runtime
  415. type of the argument in that position at a join point must have an
  416. annotation of the indicated type. For example:
  417. [source, java]
  418. ....
  419. /**
  420. * matches any join point with at least one argument, and where the
  421. * type of the first argument has the @Classified annotation
  422. */
  423. pointcut classifiedArgument() : @args(Classified,..);
  424. /**
  425. * matches any join point with three arguments, where the third
  426. * argument has an annotation of type @Untrusted.
  427. */
  428. pointcut untrustedData(Untrusted untrustedDataSource) :
  429. @args(*,*,untrustedDataSource);
  430. ....
  431. In addition to accessing annotation information at runtime through
  432. context binding, access to `AnnotatedElement` information is also
  433. available reflectively with the body of advice through the
  434. `thisJoinPoint`, `thisJoinPointStaticPart`, and
  435. `thisEnclosingJoinPointStaticPart` variables. To access annotations on
  436. the arguments, or object bound to this or target at a join point you can
  437. use the following code fragments:
  438. [source, java]
  439. ....
  440. Annotation[] thisAnnotations = thisJoinPoint.getThis().getClass().getAnnotations();
  441. Annotation[] targetAnnotations = thisJoinPoint.getTarget().getClass().getAnnotations();
  442. Annotation[] firstParamAnnotations = thisJoinPoint.getArgs()[0].getClass().getAnnotations();
  443. ....
  444. The `@within` and `@withincode` pointcut designators match any join
  445. point where the executing code is defined within a type (`@within`), or
  446. a method/constructor (`@withincode`) that has an annotation of the
  447. specified type. The form of these designators is:
  448. [source, text]
  449. ....
  450. AtWithin := '@within' '(' AnnotationOrIdentifier ')'
  451. AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')'
  452. ....
  453. Some examples of using these designators follow:
  454. `@within(Foo)`::
  455. Matches any join point where the executing code is defined within a
  456. type which has an annotation of type `Foo`.
  457. `pointcut insideCriticalMethod(Critical c) : @withincode(c);`::
  458. Matches any join point where the executing code is defined in a method
  459. or constructor which has an annotation of type `@Critical`, and
  460. exposes the value of the annotation in the parameter `c`.
  461. The `@annotation` pointcut designator matches any join point where the
  462. _subject_ of the join point has an annotation of the given type. Like
  463. the other @pcds, it can also be used for context exposure.
  464. [source, text]
  465. ....
  466. AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')'
  467. ....
  468. The subject of a join point is defined in the table in chapter one of
  469. this guide.
  470. Access to annotation information on members at a matched join point is
  471. also available through the `getSignature` method of the `JoinPoint` and
  472. `JoinPoint.StaticPart` interfaces. The `Signature` interfaces are
  473. extended with additional operations that provide access to the
  474. `java.lang.reflect` `Method, Field` and `Constructor` objects on which
  475. annnotations can be queried. The following fragment illustrates an
  476. example use of this interface to access annotation information.
  477. [source, java]
  478. ....
  479. Signature sig = thisJoinPointStaticPart.getSignature();
  480. AnnotatedElement declaringTypeAnnotationInfo = sig.getDeclaringType();
  481. if (sig instanceof MethodSignature) {
  482. // this must be a call or execution join point
  483. Method method = ((MethodSignature)sig).getMethod();
  484. }
  485. ....
  486. _Note again that it would be nicer to add the method getAnnotationInfo
  487. directly to MemberSignature, but this would once more couple the runtime
  488. library to Java 5._
  489. The `@this,@target` and `@args` pointcut designators can only be used to
  490. match against annotations that have runtime retention. The
  491. `@within, @withincode` and `@annotation` pointcut designators can only
  492. be used to match against annotations that have at least class-file
  493. retention, and if used in the binding form the annotation must have
  494. runtime retention.
  495. === Package and Parameter Annotations
  496. _Matching on package annotations is not supported in AspectJ. Support
  497. for this capability may be considered in a future release._
  498. Parameter annotation matching is being added in AspectJ1.6. Initially
  499. only matching is supported but binding will be implemented at some
  500. point. Whether the annotation specified in a pointcut should be
  501. considered to be an annotation on the parameter type or an annotation on
  502. the parameter itself is determined through the use of parentheses around
  503. the parameter type. Consider the following:
  504. [source, java]
  505. ....
  506. @SomeAnnotation
  507. class AnnotatedType {}
  508. class C {
  509. public void foo(AnnotatedType a) {}
  510. public void goo(@SomeAnnotation String s) {}
  511. }
  512. ....
  513. The method foo has a parameter of an annotated type, and can be matched
  514. by this pointcut:
  515. [source, java]
  516. ....
  517. pointcut p(): execution(* *(@SomeAnnotation *));
  518. ....
  519. When there is a single annotation specified like this, it is considered
  520. to be part of the type pattern in the match against the parameter: 'a
  521. parameter of any type that has the annotation @SomeAnnotation'.
  522. To match the parameter annotation case, the method goo, this is the
  523. pointcut:
  524. [source, java]
  525. ....
  526. pointcut p(): execution(* *(@SomeAnnotation (*)));
  527. ....
  528. The use of parentheses around the wildcard is effectively indicating
  529. that the annotation should be considered separately to the type pattern
  530. for the parameter type: 'a parameter of any type that has a parameter
  531. annotation of @SomeAnnotation'.
  532. To match when there is a parameter annotation and an annotation on the
  533. type as well:
  534. [source, java]
  535. ....
  536. pointcut p(): execution(* *(@SomeAnnotation (@SomeOtherAnnotation *)));
  537. ....
  538. The parentheses are grouping @SomeOtherAnnotation with the * to form the
  539. type pattern for the parameter, then the type @SomeAnnotation will be
  540. treated as a parameter annotation pattern.
  541. === Annotation Inheritance and pointcut matching
  542. According to the Java 5 specification, non-type annotations are not
  543. inherited, and annotations on types are only inherited if they have the
  544. `@Inherited` meta-annotation. Given the following program:
  545. [source, java]
  546. ....
  547. class C1 {
  548. @SomeAnnotation
  549. public void aMethod() {...}
  550. }
  551. class C2 extends C1 {
  552. public void aMethod() {...}
  553. }
  554. class Main {
  555. public static void main(String[] args) {
  556. C1 c1 = new C1();
  557. C2 c2 = new C2();
  558. c1.aMethod();
  559. c2.aMethod();
  560. }
  561. }
  562. aspect X {
  563. pointcut annotatedC2MethodCall() :
  564. call(@SomeAnnotation * C2.aMethod());
  565. pointcut annotatedMethodCall() :
  566. call(@SomeAnnotation * aMethod());
  567. }
  568. ....
  569. The pointcut `annotatedC2MethodCall` will not match anything since the
  570. definition of `aMethod` in `C2` does not have the annotation.
  571. The pointcut `annotatedMethodCall` matches `c1.aMethod()` but not
  572. `c2.aMethod()`. The call to `c2.aMethod` is not matched because join
  573. point matching for modifiers (the visibility modifiers, annotations, and
  574. throws clause) is based on the subject of the join point (the method
  575. actually being called).
  576. [[matchingOnAnnotationValues]]
  577. === Matching based on annotation values
  578. The `if` pointcut designator can be used to write pointcuts that match
  579. based on the values annotation members. For example:
  580. [source, java]
  581. ....
  582. pointcut txRequiredMethod(Tx transactionAnnotation) :
  583. execution(* *(..)) && @this(transactionAnnotation)
  584. && if(transactionAnnotation.policy() == TxPolicy.REQUIRED);
  585. ....
  586. [[annotations-decp]]
  587. == Using Annotations with declare statements
  588. === Declare error and declare warning
  589. Since pointcut expressions in AspectJ 5 support join point matching
  590. based on annotations, this facility can be exploited when writing
  591. `declare warning` and `declare error` statements. For example:
  592. [source, java]
  593. ....
  594. declare warning : withincode(@PerformanceCritical * *(..)) &&
  595. call(@ExpensiveOperation * *(..))
  596. : "Expensive operation called from within performance critical section";
  597. ....
  598. [source, java]
  599. ....
  600. declare error : call(* org.xyz.model.*.*(..)) &&
  601. !@within(Trusted)
  602. : "Untrusted code should not call the model classes directly";
  603. ....
  604. === declare parents
  605. The general form of a `declare parents` statement is:
  606. [source, text]
  607. ....
  608. declare parents : TypePattern extends Type;
  609. declare parents : TypePattern implements TypeList;
  610. ....
  611. Since AspectJ 5 supports annotations as part of a type pattern
  612. specification, it is now possible to match types based on the presence
  613. of annotations _with either class-file or runtime retention_. For
  614. example:
  615. `declare parents : (@Secured *) implements SecuredObject;`::
  616. All types with the `@Secured` annotation implement the `SecuredObject`
  617. inteface.
  618. `declare parents : (@Secured BankAccount+) implements SecuredObject;`::
  619. The subset of types drawn from the `BankAccount` type and any subtype
  620. of `BankAccount`, where the `@Secured` annotation is present,
  621. implement the `SecuredObject` interface.
  622. An annotation type may not be used as the target of a declare parents
  623. statement. If an annotation type is named explicitly as the target of a
  624. declare parents statement, a compilation error will result. If an
  625. annotation type is matched by a non-explicit type pattern used in a
  626. declare parents statement it will be ignored (and an XLint warning
  627. issued).
  628. === declare precedence
  629. The general form of a declare precedence statement is:
  630. [source, java]
  631. ....
  632. declare precedence : TypePatList;
  633. ....
  634. AspectJ 5 allows the type patterns in the list to include annotation
  635. information as part of the pattern specification. For example:
  636. `declare precedence : (@Security *),*;`::
  637. All aspects with the `@Security` annotation take precedence over any
  638. other aspects in the system. (Or, more informally, all
  639. security-related aspects take precedence).
  640. [[annotations-declare]]
  641. == Declare Annotation
  642. AspectJ 5 supports a new kind of declare statement,
  643. `declare annotation`. This takes different forms according to the
  644. recipient of the annotation: `declare @type` for types,
  645. `declare @method` for methods, `declare @constructor` for constructors,
  646. and `declare @field` for fields. `declare @package` may be supported in
  647. a future release.
  648. The general form is:
  649. [source, text]
  650. ....
  651. declare @<kind> : ElementPattern : Annotation ;
  652. ....
  653. Where annotation is a regular annotation expression as defined in the
  654. Java 5 language. If the annotation has the `@Target` meta-annotation,
  655. then the elements matched by `ElementPattern` must be of the kind
  656. specified by the `@Target` annotation.
  657. `ElementPattern` is defined as follows:
  658. [source, text]
  659. ....
  660. ElementPattern := TypePattern |
  661. MethodPattern |
  662. ConstructorPattern |
  663. FieldPattern
  664. ....
  665. The following examples illustrate the use of `declare annotation`.
  666. `declare @type : org.xyz.model..* : @BusinessDomain ;`::
  667. All types defined in a package with the prefix `org.xyz.model` have
  668. the `@BusinessDomain` annotation.
  669. declare @method : public * BankAccount+.*(..) :
  670. `@Secured(role="supervisor")`::
  671. All public methods in `BankAccount` and its subtypes have the
  672. annotation `@Secured(role="supervisor")`.
  673. declare @constructor : BankAccount+.new(..) :
  674. `@Secured(role="supervisor")`::
  675. All constructors in `BankAccount` and its subtypes have the annotation
  676. `@Secured(role="supervisor")`.
  677. `declare @field : * DAO+.* : @Persisted;`::
  678. All fields defined in `DAO` or its subtypes have the `@Persisted`
  679. annotation.
  680. [[annotations-itds]]
  681. == Inter-type Declarations
  682. An annotation type may not be the target of an inter-type declaration.