SpringMVC源码-创建ExceptionHandlerExceptionResolver
一、ExceptionHandlerExceptionResolver
属性是指BeanDifinition设置的属性。实现接口只关注spring提供的扩展接口。
ExceptionHandlerExceptionResolver用于处理@ExceptionHandler标注的方法抛出的异常。
二、实例化ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver
public ExceptionHandlerExceptionResolver() {
this.messageConverters = new ArrayList<>();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
if(!shouldIgnoreXml) {
try {
this.messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Error err) {
// Ignore when no TransformerFactory implementation is available
}
}
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
默认构造函数初始化messageConverters并添加ByteArrayHttpMessageConverter,StringHttpMessageConverter,AllEncompassingFormHttpMessageConverter,如果shouldIgnoreXml为false则添加SourceHttpMessageConverter。
ExceptionHandlerExceptionResolver实现了InitializingBean接口,在实例化bean之后会调用实现InitializingBean的afterPropertiesSet。
ExceptionHandlerExceptionResolver.afterPropertiesSet()
public void afterPropertiesSet() {
// Do this first, it may add ResponseBodyAdvice beans
initExceptionHandlerAdviceCache();
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);
}
}
1、initExceptionHandlerAdviceCache找出有@ControllerAdvice注解的bean中有@ExceptionHandler注解的方法并解析方法和异常类型。同时找出ResponseBodyAdvice类型的bean。
2、如果argumentResolvers为null,getDefaultArgumentResolvers添加参数处理器
3、如果returnValueHandlers为null,getDefaultReturnValueHandlers添加返回值处理器
ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache()
private void initExceptionHandlerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
if (resolver.hasExceptionMappings()) {
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
this.responseBodyAdvice.add(adviceBean);
}
}
if (logger.isDebugEnabled()) {
int handlerSize = this.exceptionHandlerAdviceCache.size();
int adviceSize = this.responseBodyAdvice.size();
if (handlerSize == 0 && adviceSize == 0) {
logger.debug("ControllerAdvice beans: none");
}
else {
logger.debug("ControllerAdvice beans: " +
handlerSize + " @ExceptionHandler, " + adviceSize + " ResponseBodyAdvice");
}
}
}
1、ControllerAdviceBean.findAnnotatedBeans从给定的ApplicationContext获取所有被@ControllerAdvice标注的bean并以集合返回
2、遍历第一步的集合,创建ExceptionHandlerMethodResolver,ExceptionHandlerMethodResolver从bean中找出所有有@ExceptionHandler注解的方法,并获取方法参数中有Throwable类型的参数,并以异常类型为key,Method为value加入mappedMethods。如果ExceptionHandlerMethodResolver有要处理的@ExceptionHandler则将bean类型为key,ExceptionHandlerMethodResolver为value加入exceptionHandlerAdviceCache。如果bean类型是ResponseBodyAdvice,则将bean加入responseBodyAdvice。
ExceptionHandlerExceptionResolver.getDefaultArgumentResolvers()
protected List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
// Annotation-based argument resolution
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new PrincipalMethodArgumentResolver());
return resolvers;
}
添加方法参数处理器。
ExceptionHandlerExceptionResolver.getDefaultReturnValueHandlers()
protected List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(
getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));
// Annotation-based return value types
handlers.add(new ServletModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(
getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
handlers.add(new ServletModelAttributeMethodProcessor(true));
return handlers;
}
添加返回值处理器。