目录
一、简介
二、@ControllerAdvice注解的处理获取
1.@ControllerAdvice注解
2.ControllerAdviceBean类
三、Request请求和Response响应对应接口切面
1.RequestBodyAdvice接口
2.ResponseBodyAdvice接口
四、Advice切面的读取和调用原理
1.RequestMappingHandlerAdapter类读取@ControllerAdvice注解类
2.RequestResponseBodyAdviceChain解析类
3.具体实现源码分析
3.1 使用HandlerMethodArgumentResolverComposite处理RequestBodyAdvice接口
3.2 HandlerMethodReturnValueHandlerComposite处理ResponseBodyAdvice接口
3.3 RequestResponseBodyMethodProcessor处理两种Advice切面接口
一、简介
@ControllerAdvice注解从名字上就可以看出来这个是针对Controller的切面增强处理注解,类似与@Controller和@RestController一样,@ControllerAdvice也有对应的@RestControllerAdvice注解用来返回序列化之后的对象。
@ControllerAdvice实际上也是一个Component,因为该注解同时也被@Component注解,搭配这个注解通常有一个注解和两个接口:
- @ExceptionHandler注解:统一处理从Controller抛出的异常,在@ControllerAdvice中可以拥有多个@ExceptionHandler和实现方法,SpringMVC将会自动判断哪个异常优先处理;
- RequestBodyAdvice接口:用来对Request请求方法体和对应方法参数进行处理,如果方法参数有多个,将会顺序调用到接口方法中来;
- ResponseBodyAdvice接口:类似RequestBodyAdvice,只是处理的对象变成了Response响应,处理的对象包括请求体和返回类型。
另外需要注意的是,@ControllerAdvice注解是一定需要搭配其它的注解或者接口使用的,否则就算这个注解类被识别到,没有具体的处理方法,SpringMVC是不会进行任何操作的。
二、@ControllerAdvice注解的处理获取
1.@ControllerAdvice注解
在分析具体实现原理前先看到其源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
// 和下面的basePackages代表的是同一个意思,只针对某些包下的类
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
// 只处理某些类所在包路径
Class<?>[] basePackageClasses() default {};
// 处理某些类和这些类的子类
Class<?>[] assignableTypes() default {};
// 处理被某些注解过的类
Class<? extends Annotation>[] annotations() default {};
}
2.ControllerAdviceBean类
这个类便是@ControllerAdvice注解对应的实体类,在这个类里面将会完成从bean工厂中获取所有被@ControllerAdvice注解过的bean,并读取注解属性将其全部返回的操作。部分关键源码如下:
public class ControllerAdviceBean implements Ordered {
// 这个bean指的就是被@ControllerAdvice注解的类对象
private final Object bean;
// bean工厂,要从bean工厂中获取bean和判断bean的类型
@Nullable
private final BeanFactory beanFactory;
// 这个类有兴趣的可以去看下,代码不多,大致作用便是存放并且判断注解的属性
private final HandlerTypePredicate beanTypePredicate;
private ControllerAdviceBean(Object bean,
@Nullable BeanFactory beanFactory) {
this.bean = bean;
this.beanFactory = beanFactory;
Class<?> beanType;
// 设置bean和beanType等属性
if (bean instanceof String) {
String beanName = (String) bean;
beanType = this.beanFactory.getType(beanName);
this.order = initOrderFromBeanType(beanType);
} else {
beanType = bean.getClass();
this.order = initOrderFromBean(bean);
}
// 从bean类型获取ControllerAdvice注解
ControllerAdvice annotation = (beanType != null ?
AnnotatedElementUtils.findMergedAnnotation(beanType,
ControllerAdvice.class) : null);
// 如果注解不为空则将注解的属性通过HandlerTypePredicate的构造器放入到
// HandlerTypePredicate对象中,以便后续判断注解属性
if (annotation != null) {
this.beanTypePredicate = HandlerTypePredicate.builder()
.basePackage(annotation.basePackages())
.basePackageClass(annotation.basePackageClasses())
.assignableType(annotation.assignableTypes())
.annotation(annotation.annotations())
.build();
} else {
// 创建一个默认的HandlerTypePredicate对象
this.beanTypePredicate = HandlerTypePredicate.forAnyHandlerType();
}
}
public boolean isApplicableToBeanType(@Nullable Class<?> beanType) {
// 这个便是外部调用判断注解属性是否满足要求的方法
return this.beanTypePredicate.test(beanType);
}
public static List<ControllerAdviceBean> findAnnotatedBeans(
ApplicationContext context) {
// 这个方法大致作用便是从bean工厂中获取所有被@ControllerAdvice注解过的
// bean对象,因为ControllerAdvice中也有@Component注解,当获得bean之后
// 再把这个bean使用ControllerAdviceBean的构造函数实例化
return Arrays.stream(BeanFactoryUtils
.beanNamesForTypeIncludingAncestors(context, Object.class))
.filter(name -> context.findAnnotationOnBean(name,
ControllerAdvice.class) != null)
.map(name -> new ControllerAdviceBean(name, context))
.collect(Collectors.toList());
}
}
三、Request请求和Response响应对应接口切面
其大致流程如下:
前面说过Request请求和Response响应都会有一个对应的接口切面,接下来先看下其接口方法。
1.RequestBodyAdvice接口
其源码如下:
public interface RequestBodyAdvice {
// 在调用本接口三个对方法体和参数进行处理的方法前都需要调用supports方法来
// 判断是否支持该方法
boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType);
// 如果方法体不为空,则在读取方法体前先执行该方法
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage,
MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>>
converterType) throws IOException;
// 在已经读取了方法体的内容后调用的方法,可以直接对方法体进行操作
Object afterBodyRead(Object body, HttpInputMessage inputMessage,
MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>>
converterType);
// 如果方法体为空所进行的处理
@Nullable
Object handleEmptyBody(@Nullable Object body,
HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>>
converterType);
}
2.ResponseBodyAdvice接口
这个接口相比于RequestBodyAdvice要简单很多,其源码如下:
public interface ResponseBodyAdvice<T> {
// 在调用本接口对返回方法体进行处理的方法前都需要调用supports方法来
// 判断是否支持该方法
boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType);
// 接口只有一个操作方法,具体可以操作的对象有返回方法体、方法返回类型和选择的
// 内容类型,如是Json或者文件等
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>>
selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
四、Advice切面的读取和调用原理
1.RequestMappingHandlerAdapter类读取@ControllerAdvice注解类
其读取@ControllerAdvice注解获取切面类源码如下:
public class RequestMappingHandlerAdapter
extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
// 保存解析参数的解析器,RequestBodyAdvice接口将会在这里面完成处理
@Nullable
private HandlerMethodArgumentResolverComposite argumentResolvers;
// 保存解析方法返回值的处理器,ResponseBodyAdvice接口将会在这里面完成处理
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
// 具体保存RequestBodyAdvice和ResponseBodyAdvice接口实现类的集合对象
private List<Object> requestResponseBodyAdvice = new ArrayList<>();
@Override
public void afterPropertiesSet() {
// 首先调用该方法去获取所有被@ControllerAdvice注解且符合是两个Advice
// 切面实现类,@RequestMapping、@ModelAttribute和@InitBinder略过
initControllerAdviceCache();
// 如果参数解析器集合为空则获取默认的
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers =
getDefaultArgumentResolvers();
this.argumentResolvers =
new HandlerMethodArgumentResolverComposite()
.addResolvers(resolvers);
}
...
// 如果返回值处理器集合为空则获取默认的
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers =
getDefaultReturnValueHandlers();
this.returnValueHandlers =
new HandlerMethodReturnValueHandlerComposite()
.addHandlers(handlers);
}
}
private void initControllerAdviceCache() {
// 如果spring上下文为空则无需进行下面的操作,因为都是基于bean工厂操作的
if (getApplicationContext() == null) {
return;
}
// 调用ControllerAdviceBean的方法,获取bean工厂中所有@ControllerAdvice
// 注解bean对象
List<ControllerAdviceBean> adviceBeans =
ControllerAdviceBean
.findAnnotatedBeans(getApplicationContext());
// 进行排序,排序的依据便是根据@Order等排序类来完成
AnnotationAwareOrderComparator.sort(adviceBeans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
// 对获取到的@ControllerAdvice注解类进行判断
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException();
}
...
// 如果实现类的类型是RequestBodyAdvice和ResponseBodyAdvice接口的
// 实现子类则将其添加到保存其对象的集合中
if (RequestBodyAdvice.class.isAssignableFrom(beanType) ||
ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
// 不为空则添加到保存两种切面集合中
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice
.addAll(0, requestResponseBodyAdviceBeans);
}
}
private List<HandlerMethodArgumentResolver>
getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
// 等下只展示使用到了两种Advice切面的类
...
// 对Request处理的重要对象,基本上都是通过这个类完成处理的
resolvers.add(new RequestResponseBodyMethodProcessor(
getMessageConverters(), this.requestResponseBodyAdvice));
// 这个类是用来处理@RequestPart注解的解析类
resolvers.add(new RequestPartMethodArgumentResolver
getMessageConverters(), this.requestResponseBodyAdvice));
...
// 对参数和返回值是HttpEntity和RequestEntity类型进行处理的类
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.requestResponseBodyAdvice));
...
return resolvers;
}
private List<HandlerMethodReturnValueHandler>
getDefaultReturnValueHandlers() {
// 等下只展示使用到了两种Advice切面的类
...
// 对参数和返回值是HttpEntity和RequestEntity类型进行处理的类
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.contentNegotiationManager,
this.requestResponseBodyAdvice));
...
// 对Response处理的重要对象,基本上都是通过这个类完成处理的
handlers.add(new RequestResponseBodyMethodProcessor(
getMessageConverters(),this.contentNegotiationManager,
this.requestResponseBodyAdvice));
...
return handlers;
}
}
2.RequestResponseBodyAdviceChain解析类
这个类的大致作用便是存储前面获得的requestResponseBodyAdvice集合对象,并提供只获取RequestBodyAdvice和ResponseBodyAdvice接口的方法,起到管理两类接口实现类的作用。其部分关键源码如下:
class RequestResponseBodyAdviceChain
implements RequestBodyAdvice, ResponseBodyAdvice<Object> {
// 保存RequestBodyAdvice接口实现类的集合对象
private final List<Object> requestBodyAdvice = new ArrayList<>(4);
// 保存ResponseBodyAdvice接口实现类的集合对象
private final List<Object> responseBodyAdvice = new ArrayList<>(4);
public RequestResponseBodyAdviceChain(
@Nullable List<Object> requestResponseBodyAdvice) {
// 分别获取集合中的RequestBodyAdvice和ResponseBodyAdvice接口实现类
// 并添加到对应的集合中,getAdviceByType方法则是对传入的集合遍历
// 一一判断是不是类是不是集合元素的父类接口,在此略过实现方法
this.requestBodyAdvice.addAll(
getAdviceByType(requestResponseBodyAdvice,
RequestBodyAdvice.class));
this.responseBodyAdvice.addAll(
getAdviceByType(requestResponseBodyAdvice,
ResponseBodyAdvice.class));
}
private <A> List<A> getMatchingAdvice(MethodParameter parameter,
Class<? extends A> adviceType) {
// 这个是等下要分析几个方法都会都用的方法,因此先大致分析一遍
// getAdvice方法是根据adviceType类型去分别获取requestBodyAdvice或者
// responseBodyAdvice集合
List<Object> availableAdvice = getAdvice(adviceType);
// 如果切面集合为空则直接返回空集合
if (CollectionUtils.isEmpty(availableAdvice)) {
return Collections.emptyList();
}
List<A> result = new ArrayList<>(availableAdvice.size());
for (Object advice : availableAdvice) {
// 如果切面是被@ControllerAdvice注解的类
if (advice instanceof ControllerAdviceBean) {
ControllerAdviceBean adviceBean =
(ControllerAdviceBean) advice;
// 转换成ControllerAdviceBean类型去调用isApplicableToBeanType
// 方法判断当前参数对象是否满足处理条件
if (!adviceBean.isApplicableToBeanType(parameter
.getContainingClass())) {
continue;
}
// 如果满足则获取切面bean
advice = adviceBean.resolveBean();
}
// 判断切面bean是否是要获取类的实现子类,是则添加
if (adviceType.isAssignableFrom(advice.getClass())) {
result.add((A) advice);
}
}
// 返回结果集
return result;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage request,
MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>>
converterType) throws IOException {
// RequestBodyAdvice几个方法的大致执行流程都差不多,因此只取一个分析
// 获取满足条件的切面bean
for (RequestBodyAdvice advice :
getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
// 一一调用切面bean的supports方法判断是否满足条件
if (advice.supports(parameter, targetType, converterType)) {
// 若满足则调用切面bean的相应方法
request = advice.beforeBodyRead(request, parameter,
targetType, converterType);
}
}
return request;
}
@Override
@Nullable
public Object beforeBodyWrite(@Nullable Object body,
MethodParameter returnType, MediaType contentType,
Class<? extends HttpMessageConverter<?>> converterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 调用processBody方法实现
return processBody(body, returnType, contentType, converterType,
request, response);
}
@Nullable
private <T> Object processBody(@Nullable Object body,
MethodParameter returnType, MediaType contentType,
Class<? extends HttpMessageConverter<?>> converterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 和RequestBodyAdvice的执行流程差不多
// 获取满足条件的切面bean
for (ResponseBodyAdvice<?> advice :
getMatchingAdvice(returnType, ResponseBodyAdvice.class)) {
// 一一调用切面bean的supports方法判断是否满足条件
if (advice.supports(returnType, converterType)) {
// 若满足则调用切面bean的相应方法
body = ((ResponseBodyAdvice<T>) advice)
.beforeBodyWrite((T) body, returnType, contentType,
converterType, request, response);
}
}
return body;
}
}
3.具体实现源码分析
因为两个接口都是从ServletInvocableHandlerMethod类进去的,因此从这个类开始分析起:
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 在invokeForRequest这个方法里将会解析参数并调用实际的处理方法处理请求
// RequestBodyAdvice接口便是在解析参数时被调用的
Object returnValue = invokeForRequest(webRequest, mavContainer,
providedArgs);
// 处理@ResponseStatus注解
setResponseStatus(webRequest);
// 处理返回方法值的,略过
...
try {
// 调用handleReturnValue方法来处理方法返回值,在这里面将会调用
// ResponseBodyAdvice接口方法
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue),
mavContainer, webRequest);
} catch (Exception ex) {
throw ex;
}
}
@Nullable
public Object invokeForRequest(NativeWebRequest request,
@Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 解析参数
Object[] args = getMethodArgumentValues(request, mavContainer,
providedArgs);
// 调用实际的bean方法处理请求
return doInvoke(args);
}
protected Object[] getMethodArgumentValues(NativeWebRequest request,
@Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 获取方法参数数组
MethodParameter[] parameters = getMethodParameters();
// 参数为空则直接返回
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
// 获得方法参数后开始遍历参数
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(
this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// 判断resolvers是否支持该参数,如果不支持则抛出异常
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException();
}
try {
// 支持处理该参数则调用解析器解析参数,RequestBodyAdvice将被处理
args[i] = this.resolvers.resolveArgument(parameter,
mavContainer, request, this.dataBinderFactory);
} catch (Exception ex) {
throw ex;
}
}
return args;
}
}
3.1 使用HandlerMethodArgumentResolverComposite处理RequestBodyAdvice接口
直接从该类的resolveArgument方法开始分析,其源码如下:
public class HandlerMethodArgumentResolverComposite
implements HandlerMethodArgumentResolver {
// 封装的解析器集合
private final List<HandlerMethodArgumentResolver> argumentResolvers =
new LinkedList<>();
// 方法参数和对应解析器的缓存集合
private final Map<MethodParameter, HandlerMethodArgumentResolver>
argumentResolverCache = new ConcurrentHashMap<>(256);
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory) throws Exception{
// 根据参数类型获取具体的参数解析器将会遍历集合调用解析器的
// supportsParameter方法来判断
HandlerMethodArgumentResolver resolver =
getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException();
}
// 调用具体的解析器解析参数,这里的resolver类型将是
// RequestResponseBodyMethodProcessor类
return resolver.resolveArgument(parameter, mavContainer,
webRequest, binderFactory);
}
@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(
MethodParameter parameter) {
// 先从缓存中获取
HandlerMethodArgumentResolver result = this.argumentResolverCache
.get(parameter);
if (result == null) {
// 如果缓存为空则遍历解析器来判断哪个满足条件
for (HandlerMethodArgumentResolver methodArgumentResolver :
this.argumentResolvers) {
// 调用解析器的supportsParameter方法判断参数是否支持
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
// 把参数类型和解析器的对应关系放到缓存中
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
}
3.2 HandlerMethodReturnValueHandlerComposite处理ResponseBodyAdvice接口
直接从handleReturnValue方法开始分析,其源码如下:
public class HandlerMethodReturnValueHandlerComposite
implements HandlerMethodReturnValueHandler {
// 封装的返回参数处理器集合对象
private final List<HandlerMethodReturnValueHandler>
returnValueHandlers = new ArrayList<>();
@Override
public void handleReturnValue(@Nullable Object returnValue,
MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
// 类似前面的参数解析器一样,这里先获取具体的处理器,支持没有缓存
// 每次获取都需要从结果处理器集合中遍历获取
HandlerMethodReturnValueHandler handler = selectHandler(returnValue,
returnType);
if (handler == null) {
throw new IllegalArgumentException();
}
// 调用真正的处理器处理返回值
handler.handleReturnValue(returnValue, returnType, mavContainer,
webRequest);
}
@Nullable
private HandlerMethodReturnValueHandler selectHandler(
@Nullable Object value, MethodParameter returnType) {
// 首先判断是否是异步的返回值
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler :
this.returnValueHandlers) {
// 如果是异步的返回值和不是AsyncHandlerMethodReturnValueHandler类型
// 则跳过本次循环
if (isAsyncValue &&
!(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
// 调用处理器的supportsReturnType方法判断是否支持返回值类型
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
}
3.3 RequestResponseBodyMethodProcessor处理两种Advice切面接口
前面两步分析了,解析参数和处理返回值都会使用到RequestResponseBodyMethodProcessor对象,因此具体解析RequestBodyAdvice和ResponseBodyAdvice接口的逻辑将会在这里面完成。其部分关键源码如下:
public class RequestResponseBodyMethodProcessor
extends AbstractMessageConverterMethodProcessor {
/**
* 这是处理RequestBodyAdvice接口的方法入口
*/
@Override
public Object resolveArgument(MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory) throws Exception{
// 解析RequestBodyAdvice接口的方法入口
parameter = parameter.nestedIfOptional();
// 调用readWithMessageConverters读取解析方法参数和方法体
Object arg = readWithMessageConverters(webRequest, parameter,
parameter.getNestedGenericParameterType());
// 后面的略过,解析RequestBodyAdvice接口只在readWithMessageConverters
// 方法中
...
return adaptArgumentIfNecessary(arg, parameter);
}
@Override
protected <T> Object readWithMessageConverters(
NativeWebRequest webRequest, MethodParameter parameter,
Type paramType) throws IOException,
HttpMediaTypeNotSupportedException,
HttpMessageNotReadableException {
// 将HttpRequest封装成特定的Request对象,最终的request对象将会
// 实现HttpInputMessage接口
HttpServletRequest servletRequest = webRequest
.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage =
new ServletServerHttpRequest(servletRequest);
// 将封装后的inputMessage对象传入readWithMessageConverters方法解析
Object arg = readWithMessageConverters(inputMessage, parameter,
paramType);
if (arg == null && checkRequired(parameter)) {
throw new HttpMessageNotReadableException();
}
return arg;
}
@Nullable
protected <T> Object readWithMessageConverters(
HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType) throws IOException,
HttpMediaTypeNotSupportedException,
HttpMessageNotReadableException {
// 前面是获取判断contentType和参数class类型的逻辑,略过
...
EmptyBodyCheckingHttpInputMessage message;
try {
// 先使用EmptyBodyCheckingHttpInputMessage封装inputMessage对象
message = new EmptyBodyCheckingHttpInputMessage(inputMessage);
// 遍历messageConverters对象
for (HttpMessageConverter<?> converter : this.messageConverters){
// 先获取内容转换器的class对象类型
Class<HttpMessageConverter<?>> converterType =
(Class<HttpMessageConverter<?>>) converter.getClass();
// 转换成GenericHttpMessageConverter类型
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()) {
// 先执行beforeBodyRead方法
HttpInputMessage msgToUse = getAdvice()
.beforeBodyRead(message, parameter,
targetType, converterType);
// 使用转换器将经过advice切面前置处理的内容转换成方法体
body = (genericConverter != null ? genericConverter
.read(targetType, contextClass, msgToUse) :
((HttpMessageConverter<T>) converter)
.read(targetClass, msgToUse));
// 对经过转换器转正具体的方法体对象进行后置处理
body = getAdvice().afterBodyRead(body, msgToUse,
parameter, targetType, converterType);
} else {
// 如果方法体为空则调用handleEmptyBody处理方法体为空的情况
body = getAdvice().handleEmptyBody(null, message,
parameter, targetType, converterType);
}
break;
}
}
}
// 对获得的body方法体进行特殊的判断
return body;
}
// -------------------------方法分割线----------------------------
/**
* 这是处理ResponseBodyAdvice接口的方法入口
*/
@Override
public void handleReturnValue(@Nullable Object returnValue,
MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws IOException,
HttpMediaTypeNotAcceptableException,
HttpMessageNotWritableException {
// 使用ResponseBodyAdvice切面处理返回值的方法入口
mavContainer.setRequestHandled(true);
// 根据webRequest分别创建对应的inputMessage和outputMessage对象
ServletServerHttpRequest inputMessage =
createInputMessage(webRequest);
ServletServerHttpResponse outputMessage =
createOutputMessage(webRequest);
// 真正执行ResponseBodyAdvice切面增强接口方法的方法
writeWithMessageConverters(returnValue, returnType, inputMessage,
outputMessage);
}
protected <T> void writeWithMessageConverters(@Nullable T value,
MethodParameter returnType,
ServletServerHttpRequest inputMessage,
ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException,
HttpMessageNotWritableException {
// 前面是对body方法体的大致判断如String类型的判断和内容类型
...
if (selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
// 遍历内容转换器
for (HttpMessageConverter<?> converter :
this.messageConverters) {
GenericHttpMessageConverter genericConverter =
(converter instanceof GenericHttpMessageConverter ?
(GenericHttpMessageConverter<?>) converter : null);
// 如果转换器不为空且这种的内容类型可以转换
if (genericConverter != null ?
((GenericHttpMessageConverter) converter)
.canWrite(targetType, valueType,
selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {
// 获取ResponseBodyAdvice切面调用其处理方法
body = getAdvice().beforeBodyWrite(body, returnType,
selectedMediaType,
(Class<? extends HttpMessageConverter<?>>)
converter.getClass(),
inputMessage, outputMessage);
// 后面略过
...
return;
}
}
}
...
}
}
至此,对于RequestBodyAdvice和ResponseBodyAdvice接口的处理调用源码便分析完毕,其中需要注意的是getAdvice()方法返回的对象类型是RequestResponseBodyAdviceChain,这里的处理逻辑都是在RequestResponseBodyAdviceChain中完成的。