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;
}

添加返回值处理器。

posted @ 2022-11-03 22:37  shigp1  阅读(60)  评论(0编辑  收藏  举报