/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.bind.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
Specialization of @Component
for classes that declare @ExceptionHandler
, @InitBinder
, or @ModelAttribute
methods to be shared across multiple @Controller
classes. Classes with @ControllerAdvice
can be declared explicitly as Spring beans or auto-detected via classpath scanning. All such beans are sorted via
AnnotationAwareOrderComparator
, i.e. based on @Order
and Ordered
, and applied in that order at runtime. For handling exceptions, an @ExceptionHandler
will be picked on the first advice with a matching exception handler method. For model attributes and InitBinder
initialization, @ModelAttribute
and @InitBinder
methods will also follow @ControllerAdvice
order.
Note: For @ExceptionHandler
methods, a root exception match will be preferred to just matching a cause of the current exception, among the handler methods of a particular advice bean. However, a cause match on a higher-priority advice will still be preferred to a any match (whether root or cause level) on a lower-priority advice bean. As a consequence, please declare your primary root exception mappings on a prioritized advice bean with a corresponding order!
By default the methods in an @ControllerAdvice
apply globally to all Controllers. Use selectors annotations()
, basePackageClasses()
, and basePackages()
(or its alias value()
) to define a more narrow subset of targeted Controllers. If multiple selectors are declared, OR logic is applied, meaning selected Controllers should match at least one selector. Note that selector checks are performed at runtime and so adding many selectors may negatively impact performance and add complexity.
Author: Rossen Stoyanchev, Brian Clozel, Sam Brannen See Also: Since: 3.2
/**
* Specialization of {@link Component @Component} for classes that declare
* {@link ExceptionHandler @ExceptionHandler}, {@link InitBinder @InitBinder}, or
* {@link ModelAttribute @ModelAttribute} methods to be shared across
* multiple {@code @Controller} classes.
*
* <p>Classes with {@code @ControllerAdvice} can be declared explicitly as Spring
* beans or auto-detected via classpath scanning. All such beans are sorted via
* {@link org.springframework.core.annotation.AnnotationAwareOrderComparator
* AnnotationAwareOrderComparator}, i.e. based on
* {@link org.springframework.core.annotation.Order @Order} and
* {@link org.springframework.core.Ordered Ordered}, and applied in that order
* at runtime. For handling exceptions, an {@code @ExceptionHandler} will be
* picked on the first advice with a matching exception handler method. For
* model attributes and {@code InitBinder} initialization, {@code @ModelAttribute}
* and {@code @InitBinder} methods will also follow {@code @ControllerAdvice} order.
*
* <p>Note: For {@code @ExceptionHandler} methods, a root exception match will be
* preferred to just matching a cause of the current exception, among the handler
* methods of a particular advice bean. However, a cause match on a higher-priority
* advice will still be preferred to a any match (whether root or cause level)
* on a lower-priority advice bean. As a consequence, please declare your primary
* root exception mappings on a prioritized advice bean with a corresponding order!
*
* <p>By default the methods in an {@code @ControllerAdvice} apply globally to
* all Controllers. Use selectors {@link #annotations()},
* {@link #basePackageClasses()}, and {@link #basePackages()} (or its alias
* {@link #value()}) to define a more narrow subset of targeted Controllers.
* If multiple selectors are declared, OR logic is applied, meaning selected
* Controllers should match at least one selector. Note that selector checks
* are performed at runtime and so adding many selectors may negatively impact
* performance and add complexity.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Sam Brannen
* @since 3.2
* @see org.springframework.stereotype.Controller
* @see RestControllerAdvice
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
Alias for the basePackages
attribute. Allows for more concise annotation declarations e.g.: @ControllerAdvice("org.my.pkg")
is equivalent to @ControllerAdvice(basePackages="org.my.pkg")
.
See Also: Since: 4.0
/**
* Alias for the {@link #basePackages} attribute.
* <p>Allows for more concise annotation declarations e.g.:
* {@code @ControllerAdvice("org.my.pkg")} is equivalent to
* {@code @ControllerAdvice(basePackages="org.my.pkg")}.
* @since 4.0
* @see #basePackages()
*/
@AliasFor("basePackages")
String[] value() default {};
Array of base packages.
Controllers that belong to those base packages or sub-packages thereof will be included, e.g.: @ControllerAdvice(basePackages="org.my.pkg")
or @ControllerAdvice(basePackages={"org.my.pkg", "org.my.other.pkg"})
.
value
is an alias for this attribute, simply allowing for more concise use of the annotation.
Also consider using basePackageClasses()
as a type-safe alternative to String-based package names.
Since: 4.0
/**
* Array of base packages.
* <p>Controllers that belong to those base packages or sub-packages thereof
* will be included, e.g.: {@code @ControllerAdvice(basePackages="org.my.pkg")}
* or {@code @ControllerAdvice(basePackages={"org.my.pkg", "org.my.other.pkg"})}.
* <p>{@link #value} is an alias for this attribute, simply allowing for
* more concise use of the annotation.
* <p>Also consider using {@link #basePackageClasses()} as a type-safe
* alternative to String-based package names.
* @since 4.0
*/
@AliasFor("value")
String[] basePackages() default {};
Type-safe alternative to value()
for specifying the packages to select Controllers to be assisted by the @ControllerAdvice
annotated class. Consider creating a special no-op marker class or interface in each package
that serves no purpose other than being referenced by this attribute.
Since: 4.0
/**
* Type-safe alternative to {@link #value()} for specifying the packages
* to select Controllers to be assisted by the {@code @ControllerAdvice}
* annotated class.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
* @since 4.0
*/
Class<?>[] basePackageClasses() default {};
Array of classes.
Controllers that are assignable to at least one of the given types will be assisted by the @ControllerAdvice
annotated class.
Since: 4.0
/**
* Array of classes.
* <p>Controllers that are assignable to at least one of the given types
* will be assisted by the {@code @ControllerAdvice} annotated class.
* @since 4.0
*/
Class<?>[] assignableTypes() default {};
Array of annotations.
Controllers that are annotated with this/one of those annotation(s) will be assisted by the @ControllerAdvice
annotated class.
Consider creating a special annotation or use a predefined one, like @RestController
.
Since: 4.0
/**
* Array of annotations.
* <p>Controllers that are annotated with this/one of those annotation(s)
* will be assisted by the {@code @ControllerAdvice} annotated class.
* <p>Consider creating a special annotation or use a predefined one,
* like {@link RestController @RestController}.
* @since 4.0
*/
Class<? extends Annotation>[] annotations() default {};
}