-
Notifications
You must be signed in to change notification settings - Fork 38.3k
Spring Annotation Programming Model
This document was introduced in conjunction with the release of Spring Framework 4.2; however, this document is a work in progress. As such, you can expect to see updates over the course of time.
Over the years, the Spring Framework has continually evolved its support for annotations, meta-annotations, and composed annotations. This document is intended to aid developers (both end users of Spring as well as developers of the Spring Framework and Spring portfolio projects) in the development and use of annotations with Spring.
The primary goals of this document include explanations of the following:
- How to use annotations with Spring.
- How to develop annotations for use with Spring.
- How Spring finds annotations (i.e., how Spring's annotation search algorithms work).
This document does not aim to explain the semantics or configuration options for particular annotations in the Spring Framework. For details on a particular annotation, developers are encouraged to consult the corresponding Javadoc or applicable sections of the reference manual.
A meta-annotation is an annotation that is declared on another
annotation. An annotation is therefore meta-annotated if it is annotated with
another annotation. For example, any annotation that is declared to be
documented is meta-annotated with @Documented
from the
java.lang.annotation
package.
A composed annotation is an annotation that is meta-annotated with one
or more annotations with the intent of combining the behavior associated with
those meta-annotations into a single custom annotation. For example, an
annotation named @TransactionalService
that is meta-annotated with Spring's
@Transactional
and @Service
annotations is a composed annotation that
combines the semantics of @Transactional
and @Service
.
The terms directly present, indirectly present, and present
have the same meanings as defined in the class-level Javadoc for
java.lang.reflect.AnnotatedElement
in Java 8.
In Spring, an annotation is considered to be meta-present on an element
if the annotation is declared as a meta-annotation on some other annotation
which is present on the element. For example, given the aforementioned
@TransactionalService
, we would say that @Transactional
is meta-present
on any class that is directly annotated with @TransactionalService
.
An attribute alias is an alias from one annotation attribute to another annotation attribute. Attributes within a set of aliases can be used interchangeably and are treated as equivalent. Attribute aliases can be categorized as follows.
-
Explicit Aliases: if two attributes in one annotation are declared as
aliases for each other via
@AliasFor
, they are explicit aliases. -
Implicit Aliases: if two or more attributes in one annotation are
declared as explicit overrides for the same attribute in a meta-annotation
via
@AliasFor
, they are implicit aliases. -
Transitive Implicit Aliases: given two or more attributes in one
annotation that are declared as explicit overrides for attributes in
meta-annotations via
@AliasFor
, if the attributes effectively override the same attribute in a meta-annotation following the law of transitivity, they are transitive implicit aliases.
An attribute override is an annotation attribute that overrides (or shadows) an annotation attribute in a meta-annotation. Attribute overrides can be categorized as follows.
-
Implicit Overrides: given attribute
A
in annotation@One
and attributeA
in annotation@Two
, if@One
is meta-annotated with@Two
, then attributeA
in annotation@One
is an implicit override for attributeA
in annotation@Two
based solely on a naming convention (i.e., both attributes are namedA
). -
Explicit Overrides: if attribute
A
is declared as an alias for attributeB
in a meta-annotation via@AliasFor
, thenA
is an explicit override forB
. -
Transitive Explicit Overrides: if attribute
A
in annotation@One
is an explicit override for attributeB
in annotation@Two
andB
is an explicit override for attributeC
in annotation@Three
, thenA
is a transitive explicit override forC
following the law of transitivity.
The Spring Composed project
is a collection of composed annotations for use with the Spring Framework
4.2.1 and higher. There you will find annotations such as @Get
, @Post
,
@Put
, and @Delete
for use with Spring MVC and annotations such as
@GetJson
, @PostJson
, etc. for use with Spring MVC REST applications.
Be sure to check out spring-composed
for further examples and inspiration
or to contribute your own custom composed annotations!
Spring Framework 4.2 introduced first-class support for declaring and looking
up aliases for annotation attributes. The @AliasFor
annotation can be used to
declare a pair of aliased attributes within a single annotation or to declare
an alias from one attribute in a custom composed annotation to an attribute in
a meta-annotation.
For example, @ContextConfiguration
from the spring-test
module is now
declared as follows:
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
// ...
}
Similarly, composed annotations that override attributes from
meta-annotations can use @AliasFor
for fine-grained control over exactly
which attributes are overridden within an annotation hierarchy. In fact, it is
even possible to declare an alias for the value
attribute of a
meta-annotation.
For example, one can develop a composed annotation with a custom attribute override as follows.
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "value")
String[] xmlFiles();
// ...
}
The short answer is: no.
The value
attributes in @Qualifier
and in stereotype annotations (e.g., @Component
, @Repository
, @Controller
, and any custom stereotype annotations) cannot be influenced by @AliasFor
. The reason is that the special handling of these value
attributes was in place years before @AliasFor
was invented. Consequently, due to backward compatibility issues it is simply not possible to use @AliasFor
with such value
attributes.
As of Spring Framework 4.2, the following annotations from core Spring use
@AliasFor
to declare aliases for their value
attributes.
org.springframework.cache.annotation.Cacheable
org.springframework.cache.annotation.CacheEvict
org.springframework.cache.annotation.CachePut
org.springframework.context.annotation.ComponentScan.Filter
org.springframework.context.annotation.ComponentScan
org.springframework.context.annotation.ImportResource
org.springframework.context.annotation.Scope
org.springframework.context.event.EventListener
org.springframework.jmx.export.annotation.ManagedResource
org.springframework.messaging.handler.annotation.Header
org.springframework.messaging.handler.annotation.Payload
org.springframework.messaging.simp.annotation.SendToUser
org.springframework.test.context.ActiveProfiles
org.springframework.test.context.ContextConfiguration
org.springframework.test.context.jdbc.Sql
org.springframework.test.context.TestExecutionListeners
org.springframework.test.context.TestPropertySource
org.springframework.transaction.annotation.Transactional
org.springframework.transaction.event.TransactionalEventListener
org.springframework.web.bind.annotation.ControllerAdvice
org.springframework.web.bind.annotation.CookieValue
org.springframework.web.bind.annotation.CrossOrigin
org.springframework.web.bind.annotation.MatrixVariable
org.springframework.web.bind.annotation.RequestHeader
org.springframework.web.bind.annotation.RequestMapping
org.springframework.web.bind.annotation.RequestParam
org.springframework.web.bind.annotation.RequestPart
org.springframework.web.bind.annotation.ResponseStatus
org.springframework.web.bind.annotation.SessionAttributes
org.springframework.web.portlet.bind.annotation.ActionMapping
org.springframework.web.portlet.bind.annotation.RenderMapping
- Document the general search algorithm(s) for annotations and meta-annotations on classes, interfaces, methods, fields, parameters, and annotations.
- What happens if an annotation is present on an element both locally and as a meta-annotation?
- How does the presence of
@Inherited
on an annotation (including custom composed annotations) affect the search algorithm?
- Document support for annotation attribute aliases configured via
@AliasFor
.- What happens if an attribute and its alias are declared in an annotation instance (with the same value or with different values)?
- Typically an
AnnotationConfigurationException
will be thrown.
- Typically an
- What happens if an attribute and its alias are declared in an annotation instance (with the same value or with different values)?
- Document support for composed annotations.
- Document support for meta-annotation attribute overrides in composed annotations.
- Document the algorithm used when looking up attributes, specifically explaining:
- implicit mapping based on naming convention (i.e., composed annotation declares an attribute with the exact same name and type as declared in the overridden meta-annotation)
- explicit mapping using
@AliasFor
- What happens if an attribute and one of its aliases are declared somewhere within the annotation hierarchy? Which one takes precedence?
- In general, how are conflicts involving annotation attributes resolved?
- Document the algorithm used when looking up attributes, specifically explaining: