diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index 46e641bbe4..b3d4ec5b5d 100644 --- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -29,6 +29,8 @@ import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.ClientDataRequest; @@ -58,6 +60,7 @@ import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.core.MethodParameter; import org.springframework.core.Ordered; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; @@ -149,8 +152,7 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator private BeanExpressionContext expressionContext; - private final Map, PortletHandlerMethodResolver> methodResolverCache = - new HashMap, PortletHandlerMethodResolver>(); + private final Map, PortletHandlerMethodResolver> methodResolverCache = new ConcurrentHashMap, PortletHandlerMethodResolver>(); /** diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index a07cc14e4d..9095a3bc04 100644 --- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -25,10 +25,11 @@ import java.lang.reflect.Method; import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import javax.portlet.ClientDataRequest; import javax.portlet.Event; import javax.portlet.EventRequest; @@ -40,6 +41,9 @@ import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.WindowState; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpSession; import org.springframework.core.ExceptionDepthComparator; import org.springframework.core.GenericTypeResolver; @@ -70,8 +74,13 @@ import org.springframework.web.servlet.View; */ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { + // dummy method placeholder + private static final Method NO_METHOD_FOUND = ClassUtils + .getMethodIfAvailable(System.class, "currentTimeMillis", null); + private WebArgumentResolver[] customArgumentResolvers; + private final Map, Map, Method>> exceptionHandlerCache = new ConcurrentHashMap, Map, Method>>(); /** * Set a custom ArgumentResolvers to use for special method parameter types. @@ -125,8 +134,22 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) { final Class handlerType = handler.getClass(); final Class thrownExceptionType = thrownException.getClass(); - final Map, Method> resolverMethods = - new LinkedHashMap, Method>(); + + Method handlerMethod = null; + Map, Method> handlers = exceptionHandlerCache + .get(handlerType); + + if (handlers != null) { + handlerMethod = handlers.get(thrownExceptionType); + if (handlerMethod != null) { + return (handlerMethod == NO_METHOD_FOUND ? null : handlerMethod); + } + } else { + handlers = new ConcurrentHashMap, Method>(); + exceptionHandlerCache.put(handlerType, handlers); + } + + final Map, Method> resolverMethods = handlers; ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { public void doWith(Method method) { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index d0916c2aaa..328288a1b1 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -27,13 +27,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -44,7 +45,6 @@ import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; @@ -182,8 +182,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator private BeanExpressionContext expressionContext; - private final Map, ServletHandlerMethodResolver> methodResolverCache = - new HashMap, ServletHandlerMethodResolver>(); + private final Map, ServletHandlerMethodResolver> methodResolverCache = new ConcurrentHashMap, ServletHandlerMethodResolver>(); + + private final Map, Boolean> sessionAnnotatedClassesCache = new ConcurrentHashMap, Boolean>(); public AnnotationMethodHandlerAdapter() { @@ -390,7 +391,16 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if (AnnotationUtils.findAnnotation(handler.getClass(), SessionAttributes.class) != null) { + Class clazz = ClassUtils.getUserClass(handler); + Boolean annotated = sessionAnnotatedClassesCache.get(clazz); + + if (annotated == null) { + annotated = Boolean.valueOf(AnnotationUtils.findAnnotation(handler + .getClass(), SessionAttributes.class) != null); + sessionAnnotatedClassesCache.put(clazz, annotated); + } + + if (annotated) { // Always prevent caching in case of session attribute management. checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); // Prepare cached set of session attributes names. @@ -498,7 +508,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator */ private class ServletHandlerMethodResolver extends HandlerMethodResolver { - private final Map mappings = new HashMap(); + private final Map mappings = new ConcurrentHashMap(); private ServletHandlerMethodResolver(Class handlerType) { init(handlerType); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index be2c68c0ed..713fe66f1e 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -27,10 +27,11 @@ import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -82,6 +83,12 @@ import org.springframework.web.servlet.support.RequestContextUtils; */ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { + // dummy method placeholder + private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null); + + private final Map, Map, Method>> exceptionHandlerCache = + new ConcurrentHashMap, Map, Method>>(); + private WebArgumentResolver[] customArgumentResolvers; private HttpMessageConverter[] messageConverters = @@ -147,10 +154,24 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc * @return the best matching method; or null if none is found */ private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) { - final Class handlerType = handler.getClass(); + final Class handlerType = ClassUtils.getUserClass(handler); final Class thrownExceptionType = thrownException.getClass(); - final Map, Method> resolverMethods = - new LinkedHashMap, Method>(); + Method handlerMethod = null; + + Map, Method> handlers = exceptionHandlerCache.get(handlerType); + + if (handlers != null) { + handlerMethod = handlers.get(thrownExceptionType); + if (handlerMethod != null) { + return (handlerMethod == NO_METHOD_FOUND ? null : handlerMethod); + } + } + else { + handlers = new ConcurrentHashMap, Method>(); + exceptionHandlerCache.put(handlerType, handlers); + } + + final Map, Method> resolverMethods = handlers; ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { public void doWith(Method method) { @@ -174,7 +195,9 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } }); - return getBestMatchingMethod(resolverMethods, thrownException); + handlerMethod = getBestMatchingMethod(resolverMethods, thrownException); + handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod)); + return handlerMethod; } /**