Los métodos anotados con @ExceptionHandler, @InitBinder y @ModelAttribute se aplican solo a la clase marcada con anotación de @Controller, o a la jerarquía de clases en las que están declarados. Si, en cambio, se declaran en una clase anotada con @ControllerAdvice o @RestControllerAdvice, entonces se aplican a cualquier controlador. Además, a partir de la versión 5.3, los métodos anotados con @ExceptionHandler en @ControllerAdvice se pueden usar para manejar excepciones de cualquier controlador marcado con @Controller. anotación o cualquier otro controlador.

La anotación

La @ControllerAdvice está metaanotada con la anotación @Component y, por lo tanto, se puede registrar como un Spring Bean mediante el escaneo de componentes. La anotación @RestControllerAdvice está metaanotada con la anotación @ControllerAdvice y la anotación @ResponseBody, lo que significa que los métodos marcados con annotation @ExceptionHandler tendrá su valor de retorno representado a través de la transformación del mensaje del cuerpo de la respuesta en lugar de a través de las vistas HTML.

Al inicio, RequestMappingHandlerMapping y ExceptionHandlerExceptionResolver detectan beans de controlador equipados con Advice y los aplican en tiempo de ejecución. Los métodos globales marcados con la anotación @ExceptionHandler de @ControllerAdvice se aplican después de los locales de @Controller. Por el contrario, los métodos globales con las anotaciones @ModelAttribute y @InitBinder se aplican antes de los locales.

La anotación @ControllerAdvice tiene atributos que le permiten limitar el conjunto de controladores y manejadores a los que se aplican. Por ejemplo:

Java

// Apunte a todos los controladores anotados con @RestController
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}
// Apunta a todos los controladores en paquetes específicos
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}
// Apunta a todos los controladores asignados a clases específicas
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}
Kotlin

// Apunte a todos los controladores anotados con @RestController
@ControllerAdvice(annotations = [RestController::class])
class ExampleAdvice1
// Apunta a todos los controladores en paquetes específicos
@ControllerAdvice("org.example.controllers")
class ExampleAdvice2
// Apunta a todos los controladores asignados a clases específicas
@ControllerAdvice(assignableTypes = [ControllerInterface::class, AbstractController::class])
class ExampleAdvice3

Los selectores del ejemplo anterior se evalúan en tiempo de ejecución y pueden afectar negativamente al rendimiento si se utilizan de forma extensiva. Para obtener más información, consulte la anotación javadoc @ControllerAdvice.