- Notifications
You must be signed in to change notification settings - Fork38.8k
Spring Annotation Programming Model
Table of Contents
Over the years, the Spring Framework has continually evolved its support forannotations,meta-annotations, andcomposed annotations. This document isintended to aid developers (both end users of Spring as well as developers ofthe Spring Framework and Spring portfolio projects) in the development and useof annotations with Spring.
See also:MergedAnnotation API internals
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 Springfinds annotations (i.e., how Spring's annotation searchalgorithms work).
This document does not aim to explain the semantics or configuration optionsfor particular annotations in the Spring Framework. For details on a particularannotation, developers are encouraged to consult the corresponding Javadoc orapplicable sections of the reference manual.
Ameta-annotation is an annotation that is declared on anotherannotation. An annotation is thereforemeta-annotated if it is annotated withanother annotation. For example, any annotation that is declared to bedocumented is meta-annotated with@Documented from thejava.lang.annotation package.
Astereotype annotation is an annotation that is used to declare therole that a component plays within the application. For example, the@Repository annotation in the Spring Framework is a marker for any classthat fulfills the role orstereotype of a repository (also known asData Access Object or DAO).
@Component is a generic stereotype for any Spring-managed component.Any component annotated with@Component is a candidate forcomponent scanning. Similarly, any component annotated with an annotationthat is itself meta-annotated with@Component is also a candidate forcomponent scanning. For example,@Service is meta-annotated with@Component.
Core Spring provides several stereotype annotations out of the box,including but not limited to:@Component,@Service,@Repository,@Controller,@RestController, and@Configuration.@Repository,@Service, etc. are specializations of@Component.
Acomposed annotation is an annotation that ismeta-annotated with oneor more annotations with the intent of combining the behavior associated withthose meta-annotations into a single custom annotation. For example, anannotation named@TransactionalService that is meta-annotated with Spring's@Transactional and@Service annotations is a composed annotation thatcombines the semantics of@Transactional and@Service.@TransactionalService is technically also a customstereotype annotation.
The termsdirectly present,indirectly present, andpresenthave the same meanings as defined in the class-level Javadoc forjava.lang.reflect.AnnotatedElement in Java 8.
In Spring, an annotation is considered to bemeta-present on an elementif the annotation is declared as a meta-annotation on some other annotationwhich ispresent on the element. For example, given the aforementioned@TransactionalService, we would say that@Transactional ismeta-presenton any class that is directly annotated with@TransactionalService.
Anattribute alias is an alias from one annotation attribute to anotherannotation attribute. Attributes within a set of aliases can be usedinterchangeably and are treated as equivalent. Attribute aliases can becategorized as follows.
- Explicit Aliases: if two attributes in one annotation are declared asaliases for each other via
@AliasFor, they areexplicit aliases. - Implicit Aliases: if two or more attributes in one annotation aredeclared as explicit overrides for the same attribute in a meta-annotationvia
@AliasFor, they areimplicit aliases. - Transitive Implicit Aliases: given two or more attributes in oneannotation that are declared as explicit overrides for attributes inmeta-annotations via
@AliasFor, if the attributeseffectively overridethe same attribute in a meta-annotation following thelaw of transitivity,they aretransitive implicit aliases.
Anattribute override is an annotation attribute thatoverrides (orshadows) an annotation attribute in a meta-annotation. Attribute overridescan be categorized as follows.
- Implicit Overrides: given attribute
Ain annotation@OneandattributeAin annotation@Two, if@Oneis meta-annotated with@Two,then attributeAin annotation@Oneis animplicit override forattributeAin annotation@Twobased solely on a naming convention (i.e.,both attributes are namedA). - Explicit Overrides: if attribute
Ais declared as an alias forattributeBin a meta-annotation via@AliasFor, thenAis anexplicitoverride forB. - Transitive Explicit Overrides: if attribute
Ain annotation@Oneisan explicit override for attributeBin annotation@TwoandBis anexplicit override for attributeCin annotation@Three, thenAis atransitive explicit override forCfollowing thelaw of transitivity.
Many of the annotations within the Spring Framework and Spring portfolioprojects make use of the@AliasFor annotation for declaringattributealiases andattribute overrides. Common examples include@RequestMapping,@GetMapping, and@PostMapping from Spring MVC as well as annotationssuch as@SpringBootApplication and@SpringBootTest from Spring Boot.
The following sections provide code snippets to demonstrate these features.
Spring Framework 4.2 introduced first-class support for declaring and lookingup aliases for annotation attributes. The@AliasFor annotation can be used todeclare a pair of aliased attributeswithin a single annotation or to declarean alias from one attribute in a custom composed annotation to an attribute ina meta-annotation.
For example,@ContextConfiguration from thespring-test module isdeclared as follows.
public @interfaceContextConfiguration {@AliasFor("locations")String[]value()default {};@AliasFor("value")String[]locations()default {};// ...}
Thelocations attribute is declared as an alias for thevalueattribute, and vice versa. Consequently, the following declarationsof@ContextConfiguration are equivalent.
@ContextConfiguration("/test-config.xml")publicclassMyTests {/* ... */ }
@ContextConfiguration(value ="/test-config.xml")publicclassMyTests {/* ... */ }
@ContextConfiguration(locations ="/test-config.xml")publicclassMyTests {/* ... */ }
Similarly,composed annotations that override attributes frommeta-annotations can use@AliasFor for fine-grained control over exactlywhich attributes are overridden within an annotation hierarchy. In fact, it iseven possible to declare an alias for thevalue attribute of ameta-annotation.
For example, one can develop a composed annotation with a custom attributeoverride as follows.
@ContextConfigurationpublic @interfaceMyTestConfig {@AliasFor(annotation =ContextConfiguration.class,attribute ="value")String[]xmlFiles();// ...}
The above example demonstrates how developers can implement their owncustomcomposed annotations; whereas, the following demonstrates thatSpring itself makes use of this feature in many core Spring annotations.
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documented@RequestMapping(method =RequestMethod.GET)public @interfaceGetMapping {/** * Alias for {@link RequestMapping#name}. */@AliasFor(annotation =RequestMapping.class)Stringname()default"";/** * Alias for {@link RequestMapping#value}. */@AliasFor(annotation =RequestMapping.class)String[]value()default {};/** * Alias for {@link RequestMapping#path}. */@AliasFor(annotation =RequestMapping.class)String[]path()default {};// ...}
TheSpring Composed projectis a collection ofcomposed annotations for use with the Spring Framework4.2.1 and higher. There you will find annotations such as@Get,@Post,@Put, and@Delete that served as the inspiration for the@GetMapping,@PostMapping,@PutMapping, and@DeleteMapping annotations that arenow part of Spring MVC and Spring WebFlux.
Feel free to check outspring-composed for further examples and inspirationfor how you can implement your own customcomposed annotations, and for abit of geek humor and entertainment that further demonstrate the power of@AliasFor, take a look atSpring Polyglot.
No, thevalue attribute in@Qualifiercannot be influenced by@AliasFor. The reason is that the special handling of thevalue attribute for qualifiers was in place years before@AliasFor was invented, and that special handling is still in place.
The short answer is: No, not until Spring Framework 6.1
Prior to Spring Framework 6.1, thevalue attribute instereotype annotations (e.g.,@Component,@Repository,@Controller, and any custom stereotype annotations) could not be influenced by@AliasFor. The rationale is analogous to the explanation given for@Qualifier above. However, Spring Framework 6.1 introduces full support for aliasing thevalue attribute in@Component via@AliasFor. For example, see the source declaration of thename attribute in@ControllerAdvice.
- Document the general search algorithm(s) for annotations and meta-annotations on classes, interfaces, methods, fields, parameters, and annotations.
- What happens if an annotation ispresent on an element both locally and as a meta-annotation?
- How does the presence of
@Inheritedon an annotation (including custom composed annotations) affect the search algorithm?
- Document support for annotation attribute aliases configured via
@AliasFor.- What happens if an attributeand its alias are declared in an annotation instance (with the same value or with different values)?
- Typically an
AnnotationConfigurationExceptionwill be thrown.
- Typically an
- What happens if an attributeand its alias are declared in an annotation instance (with the same value or with different values)?
- Document support forcomposed 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 theoverridden meta-annotation)
- explicit mapping using
@AliasFor
- What happens if an attributeand one of its aliases are declared somewhere within the annotationhierarchy? Which one takes precedence?
- In general, how are conflicts involving annotation attributes resolved?
- Document the algorithm used when looking up attributes, specifically explaining: