曹耘豪的博客

Spring之ControllerAdvice

  1. @ControllerAdvice
    1. 初始化
    2. 注解支持作用范围
  2. RequestBodyAdvice原理
  3. ResponseBodyAdvice原理
  4. @ExceptionHandler原理
    1. 初始化
    2. 获取对应的异常处理器

@ControllerAdvice

初始化

RequestMappingHandlerAdapter.initControllerAdviceCache

ControllerAdviceBean.findAnnotatedBeans获取所有ControllerAdviceBean,排序取决于Order

对于每个bean:

注解支持作用范围

RequestBodyAdvice原理

AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters

  1. 先遍历寻找HttpMessageConverter
  2. 链式执行beforeBodyRead(所有满足条件的RequestBodyAdvice,顺序取决于Order
  3. HttpMessageConverter解析body
  4. 链式执行afterBodyRead
AbstractMessageConverterMethodArgumentResolver.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
message = new EmptyBodyCheckingHttpInputMessage(inputMessage);

for (HttpMessageConverter<?> converter : this.messageConverters) {
Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
GenericHttpMessageConverter<?> genericConverter =
(converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) :
(targetClass != null && converter.canRead(targetClass, contentType))) {
if (message.hasBody()) {
HttpInputMessage msgToUse =
getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
}
else {
body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
}
break;
}
}

ResponseBodyAdvice原理

RequestBodyAdvice类似

  1. 先遍历寻找HttpMessageConverter
  2. 链式执行beforeBodyWrite
  3. 执行converter.write

@ExceptionHandler原理

初始化

ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache

ControllerAdviceBean.findAnnotatedBeans获取所有ControllerAdviceBean

对于每个bean:

获取对应的异常处理器

ExceptionHandlerExceptionResolver.getExceptionHandlerMethod

   /