private void initExceptionHandlerAdviceCache() { if (getApplicationContext() == null) { return; } if (logger.isDebugEnabled()) { logger.debug("Looking for exception mappings: " + getApplicationContext()); } List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(adviceBeans); for (ControllerAdviceBean adviceBean : adviceBeans) { ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(adviceBean.getBeanType()); if (resolver.hasExceptionMappings()) { this.exceptionHandlerAdviceCache.put(adviceBean, resolver); if (logger.isInfoEnabled()) { logger.info("Detected @ExceptionHandler methods in " + adviceBean); } } if (ResponseBodyAdvice.class.isAssignableFrom(adviceBean.getBeanType())) { this.responseBodyAdvice.add(adviceBean); if (logger.isInfoEnabled()) { logger.info("Detected ResponseBodyAdvice implementation in " + adviceBean); } } } }
/** * Find an {@code @ExceptionHandler} method for the given exception. The default implementation * searches methods in the class hierarchy of the controller first and if not found, it continues * searching for additional {@code @ExceptionHandler} methods assuming some {@linkplain * ControllerAdvice @ControllerAdvice} Spring-managed beans were detected. * * @param handlerMethod the method where the exception was raised (may be {@code null}) * @param exception the raised exception * @return a method to handle the exception, or {@code null} */ protected ServletInvocableHandlerMethod getExceptionHandlerMethod( HandlerMethod handlerMethod, Exception exception) { Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null); if (handlerMethod != null) { ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); if (resolver == null) { resolver = new ExceptionHandlerMethodResolver(handlerType); this.exceptionHandlerCache.put(handlerType, resolver); } Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); } } for (Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) { if (entry.getKey().isApplicableToBeanType(handlerType)) { ExceptionHandlerMethodResolver resolver = entry.getValue(); Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(entry.getKey().resolveBean(), method); } } } return null; }
protected InvocableHandlerMethod findExceptionHandler( HandlerMethod handlerMethod, Exception exception) { if (handlerMethod == null) { return null; } Class<?> handlerType = handlerMethod.getBeanType(); ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); if (resolver == null) { resolver = new ExceptionHandlerMethodResolver(handlerType); this.exceptionHandlerCache.put(handlerType, resolver); } Method method = resolver.resolveMethod(exception); return (method != null ? new InvocableHandlerMethod(handlerMethod.getBean(), method) : null); }
/** * Find the @{@link ExceptionHandler} method for the given exception. The default implementation * searches @{@link ExceptionHandler} methods in the class hierarchy of the method that raised the * exception. * * @param handlerMethod the method where the exception was raised, possibly {@code null} * @param exception the raised exception * @return a method to handle the exception, or {@code null} */ protected ServletInvocableHandlerMethod getExceptionHandlerMethod( HandlerMethod handlerMethod, Exception exception) { if (handlerMethod != null) { Class<?> handlerType = handlerMethod.getBeanType(); ExceptionHandlerMethodResolver resolver = this.exceptionHandlersByType.get(handlerType); if (resolver == null) { resolver = new ExceptionHandlerMethodResolver(handlerType); this.exceptionHandlersByType.put(handlerType, resolver); } Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); } } return getGlobalExceptionHandlerMethod(exception); }