目录

1. 启动时扫描 @ControllerAdvice 注解:

2. ControllerAdviceBeanPostProcessor:

3. ExceptionHandlerMethodResolver:

4. 注册异常处理方法:

5. 请求处理和异常捕获:

6. ExceptionHandlerExceptionResolver:

总结:


1. 启动时扫描 @ControllerAdvice 注解:

在 Spring Boot 应用程序启动过程中,Spring 会扫描所有的类,寻找带有 @ControllerAdvice 注解的类。这是通过 ConfigurationClassPostProcessor

2. ControllerAdviceBeanPostProcessor:

ControllerAdviceBeanPostProcessor 是一个实现了 BeanPostProcessor 接口的类。在应用程序启动过程中,所有 Bean 初始化之后,ControllerAdviceBeanPostProcessor 的 postProcessAfterInitialization 方法会被调用。该方法负责处理带有 @ControllerAdvice 注解的类;

postProcessAfterInitialization:

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

    if (bean instanceof ControllerAdviceBean) {

        ControllerAdviceBean adviceBean = (ControllerAdviceBean) bean;

        Class<?> beanType = adviceBean.getBeanType();

        if (beanType != null) {

            ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);

            if (resolver.hasExceptionMappings()) {

                this.exceptionHandlerAdviceCache.put(adviceBean, resolver);

            }

        }

    }

    return bean;

}

3. ExceptionHandlerMethodResolver:

在上述 ControllerAdviceBeanPostProcessor 的方法中,会创建 ExceptionHandlerMethodResolver 实例来扫描带有 @ControllerAdvice 注解的类中的所有方法,找到使用了 @ExceptionHandler 注解的异常处理方法。这些方法会被添加到一个映射表中,以便后续处理异常时能找到对应的处理方法。

4. 注册异常处理方法:

在 ControllerAdviceBeanPostProcessor 中,异常处理方法会被注册到一个全局的异常处理器映射表(exceptionHandlerAdviceCache)中。映射表将异常类型与相应的处理方法关联起来,以便在发生异常时能够找到正确的处理方法。

5. 请求处理和异常捕获:

当 Spring Boot 应用程序接收到一个请求时,它会将请求分派给相应的 Controller 方法。在执行 Controller 方法时,如果抛出了异常,DispatcherServlet 会将异常传递给 HandlerExceptionResolver 来处理。在这里,ExceptionHandlerExceptionResolver 会被调用。

6. ExceptionHandlerExceptionResolver:

ExceptionHandlerExceptionResolver 类负责在全局异常处理器映射表(exceptionHandlerAdviceCache)中查找与异常类型关联的处理方法,并执行这个方法来处理异常。具体实现在 doResolveHandlerMethodException 方法中:

protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {

    // ...

    ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);

    if (exceptionHandlerMethod == null) {

       return null;

   }

   // ...

   try {

       exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exceptionResult);

   } catch (Exception invocationEx) {

       // ...

   }

   // ...

   return ModelAndViewResolver.UNRESOLVED;

}

在这个方法中,`ExceptionHandlerExceptionResolver` 会根据异常类型查找对应的处理方法。如果找到了适合的处理方法,它将使用 `ServletInvocableHandlerMethod` 类的实例来执行该方法,并将异常处理结果(通常是一个 ModelAndView 对象或 ResponseEntity 对象)返回给客户端;

总结:

`@ControllerAdvice` 的工作原理在 Spring Boot 应用程序启动时涉及到多个组件和步骤;

在启动过程中,`ControllerAdviceBeanPostProcessor` 会扫描带有 `@ControllerAdvice` 注解的类,`ExceptionHandlerMethodResolver` 会扫描这些类中的异常处理方法并将它们注册到全局异常处理器映射表中。当请求处理过程中发生异常时,`ExceptionHandlerExceptionResolver` 会从映射表中查找并执行相应的异常处理方法