[[webflux-ann-controller-advice]]
= Controller Advice

[.small]#xref:web/webmvc/mvc-controller/ann-advice.adoc[See equivalent in the Servlet stack]#

Typically, the `@ExceptionHandler`, `@InitBinder`, and `@ModelAttribute` methods apply
within the `@Controller` class (or class hierarchy) in which they are declared. If you
want such methods to apply more globally (across controllers), you can declare them in a
class annotated with `@ControllerAdvice` or `@RestControllerAdvice`.

`@ControllerAdvice` is annotated with `@Component`, which means that such classes can be
registered as Spring beans through xref:core/beans/java/instantiating-container.adoc#beans-java-instantiating-container-scan[component scanning]
. `@RestControllerAdvice` is a composed annotation that is annotated
with both `@ControllerAdvice` and `@ResponseBody`, which essentially means
`@ExceptionHandler` methods are rendered to the response body through message conversion
(versus view resolution or template rendering).

On startup, the infrastructure classes for `@RequestMapping` and `@ExceptionHandler`
methods detect Spring beans annotated with `@ControllerAdvice` and then apply their
methods at runtime. Global `@ExceptionHandler` methods (from a `@ControllerAdvice`) are
applied _after_ local ones (from the `@Controller`). By contrast, global `@ModelAttribute`
and `@InitBinder` methods are applied _before_ local ones.

By default, `@ControllerAdvice` methods apply to every request (that is, all controllers),
but you can narrow that down to a subset of controllers by using attributes on the
annotation, as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	// Target all Controllers annotated with @RestController
	@ControllerAdvice(annotations = RestController.class)
	public class ExampleAdvice1 {}

	// Target all Controllers within specific packages
	@ControllerAdvice("org.example.controllers")
	public class ExampleAdvice2 {}

	// Target all Controllers assignable to specific classes
	@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
	public class ExampleAdvice3 {}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	// Target all Controllers annotated with @RestController
	@ControllerAdvice(annotations = [RestController::class])
	public class ExampleAdvice1 {}

	// Target all Controllers within specific packages
	@ControllerAdvice("org.example.controllers")
	public class ExampleAdvice2 {}

	// Target all Controllers assignable to specific classes
	@ControllerAdvice(assignableTypes = [ControllerInterface::class, AbstractController::class])
	public class ExampleAdvice3 {}
----
======

The selectors in the preceding example are evaluated at runtime and may negatively impact
performance if used extensively. See the
{spring-framework-api}/web/bind/annotation/ControllerAdvice.html[`@ControllerAdvice`]
javadoc for more details.
