在SpringMVC自动装配核心类之WebMvcAutoConfiguration
内部实例化EnableWebMvcConfiguration
过程中会触发其父类WebMvcConfigurationSupport
内部初始化HandlerExceptionResolver
。
1.WebMvcConfigurationSupport
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
@Bean
public HandlerExceptionResolver handlerExceptionResolver(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
}
extendHandlerExceptionResolvers(exceptionResolvers);
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
composite.setOrder(0);
composite.setExceptionResolvers(exceptionResolvers);
return composite;
}
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,
ContentNegotiationManager manager) {
//得到 ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
...
exceptionHandlerResolver.afterPropertiesSet();
exceptionResolvers.add(exceptionHandlerResolver);
ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
responseStatusResolver.setMessageSource(this.applicationContext);
exceptionResolvers.add(responseStatusResolver);
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
}
最终返回HandlerExceptionResolver类型为HandlerExceptionResolverComposite
。并且其resolvers
属性包含了三种元素分别为ExceptionHandlerExceptionResolver
、ResponseStatusExceptionResolver
、DefaultHandlerExceptionResolver
。
不管应用中是否显式指定全局异常拦截注解@ControllerAdvice。SpringMVC都会执行初始化异常处理解析器【HandlerExceptionResolver】的逻辑,唯一的区别就是ExceptionHandlerExceptionResolver内部其属性exceptionHandlerAdviceCache是否存在元素,元素存在与否表明了应用中是否显式指定全局异常拦截注解@ControllerAdvice。
1.2.ExceptionHandlerExceptionResolver
ControllerAdviceBean
是对全局异常Handler的抽象,ExceptionHandlerMethodResolver
是对Handler核心方法的抽象。
最终目的是建立并在属性exceptionHandlerAdviceCache
缓存 ControllerAdviceBean & ExceptionHandlerMethodResolver 的对应关系,方便后续直接使用。
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
implements ApplicationContextAware, InitializingBean {
Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = new LinkedHashMap<>();
public void afterPropertiesSet() {
initExceptionHandlerAdviceCache();
...
}
private void initExceptionHandlerAdviceCache() {
// 返回 @ControllerAdvice 注解的类
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
for (ControllerAdviceBean adviceBean : adviceBeans) {
// 全局异常拦截handler:其实就是指@ControllerAdvice注解的类
Class<?> beanType = adviceBean.getBeanType();
// 封装全局异常拦截handler相关属性:核心是拦截handler中的方法
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
if (resolver