Chapter 2. Annotations

Table of Contents

Annotations in Java 5
Using Annotations
Retention Policies
Accessing Annotations at Runtime
Annotation Inheritance
Annotating Aspects
Join Point Matching based on Annotations
Annotation Patterns
Type Patterns
Signature Patterns
Example Pointcuts
Runtime type matching and context exposure
Package and Parameter Annotations
Annotation Inheritance and pointcut matching
Matching based on annotation values
Using Annotations with declare statements
Declare error and declare warning
declare parents
declare precedence
Declare Annotation
Inter-type Declarations

Annotations in Java 5

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.

Using Annotations

Java 5 introduces annotation types which can be used to express metadata relating to program members in the form of annotations. 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 @ symbol. For example, the following piece of code uses the @Deprecated annotation to indicate that the obsoleteMethod() has been deprecated:

		@Deprecated
		public void obsoleteMethod() { ... }
		

Annotations may be marker annotations, single-valued annotations, or multi-valued annotations. 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:

		@SuppressWarnings({"unchecked"})
		public void someMethod() {...}
		

or

		@SuppressWarnings(value={"unchecked"})
		public void someMethod() {...}
		

Multi-value annotations must use the member-name=value syntax to specify annotation values. For example:

		@Authenticated(role="supervisor",clearanceLevel=5)
		public void someMethod() {...}
		

Retention Policies

Annotations can have one of three retention policies:

Source-file retention

Annotations with source-file retention are read by the compiler during the compilation process, but are not rendered in the generated .class files.

Class-file retention

This is the default retention policy. Annotations with class-file retention are read by the compiler and also retained in the generated .class files.

Runtime retention

Annotations with runtime retention are read by the compiler, retained in the generated .class files, and also made available at runtime.

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.

Accessing Annotations at Runtime

Java 5 supports a new interface, java.lang.reflect.AnnotatedElement, that is implemented by the reflection classes in Java (Class, Constructor, Field, Method, and Package). This interface gives you access to annotations that have runtime retention via the getAnnotation, getAnnotations, and isAnnotationPresent. Because annotation types are just regular Java classes, the annotations returned by these methods can be queried just like any regular Java object.

Annotation Inheritance

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.

By default annotations are not inherited. Given the following program

			@MyAnnotation
			class Super {
			  @Oneway public void foo() {}
			}
			
			class Sub extends Super {
			  public void foo() {}
			}
			

Then Sub does not have the MyAnnotation annotation, and Sub.foo() is not an @Oneway method, despite the fact that it overrides Super.foo() which is.

If an annotation type has the meta-annotation @Inherited then an annotation of that type on a class will cause the annotation to be inherited by sub-classes. So, in the example above, if the MyAnnotation type had the @Inherited attribute, then Sub would have the MyAnnotation annotation.

@Inherited 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.