在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。
1.2.ExceptionHandlerExceptionResolver

public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
		implements ApplicationContextAware, InitializingBean {
		
	Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = new LinkedHashMap<>();
	
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBodyAdvice beans
		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.hasExceptionMappings()) {
				this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
			}
			if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				this.responseBodyAdvice.add(adviceBean);
			}
		}
	}
}
 
public class ControllerAdviceBean implements Ordered {
	public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {
		List<ControllerAdviceBean> adviceBeans = new ArrayList<>();
		// 利用应用上下文获取IOC容器中全部的bean
		for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class)) {
			if (!ScopedProxyUtils.isScopedTarget(name)) {
				ControllerAdvice controllerAdvice = context.findAnnotationOnBean(name, ControllerAdvice.class);
				if (controllerAdvice != null) {
					adviceBeans.add(new ControllerAdviceBean(name, context, controllerAdvice));
				}
			}
		}
		OrderComparator.sort(adviceBeans);
		return adviceBeans;
	}
}
 
@ControllerAdvice是一个组合注解,内部存在@Component。所以也是Spring启动过程中被扫描的对象。
public class ExceptionHandlerMethodResolver {
    MethodFilter EXCEPTION_HANDLER_METHODS = method ->
			AnnotatedElementUtils.hasAnnotation(method, ExceptionHandler.class);
			
	Map<Class<? extends Throwable>, Method> mappedMethods = new HashMap<>(16);
	
	public ExceptionHandlerMethodResolver(Class<?> handlerType) {
		// 在 @ControllerAdvice 注解的类中获取 @ExceptionHandler 注解的方法
		for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {
			// 获取 @ExceptionHandler 其属性value的值,即代表拦截需要处理的异常
			for (Class<? extends Throwable> exceptionType : detectExceptionMappings(method)) {
				// 异常类型 & @ExceptionHandler 注解的方法
				addExceptionMapping(exceptionType, method);
			}
		}
	}
	
	private void addExceptionMapping(Class<? extends Throwable> exceptionType, Method method) {
		Method oldMethod = this.mappedMethods.put(exceptionType, method);
	}
}
                
















![[DRAFT] LLVM ThinLTO原理分析](https://img-blog.csdnimg.cn/1f57982a5dbf446e9a6ea045468ab999.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55S15b2x5peF6KGM5pWy5Luj56CB,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

