- minor performance improvements to servlet and portlet handlers
This commit is contained in:
Costin Leau
2010-10-31 17:46:15 +00:00
parent caf1a0875a
commit 01e79cfedd
4 changed files with 74 additions and 16 deletions

View File

@@ -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<Class<?>, ServletHandlerMethodResolver> methodResolverCache =
new HashMap<Class<?>, ServletHandlerMethodResolver>();
private final Map<Class<?>, ServletHandlerMethodResolver> methodResolverCache = new ConcurrentHashMap<Class<?>, ServletHandlerMethodResolver>();
private final Map<Class<?>, Boolean> sessionAnnotatedClassesCache = new ConcurrentHashMap<Class<?>, 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<Method, RequestMappingInfo> mappings = new HashMap<Method, RequestMappingInfo>();
private final Map<Method, RequestMappingInfo> mappings = new ConcurrentHashMap<Method, RequestMappingInfo>();
private ServletHandlerMethodResolver(Class<?> handlerType) {
init(handlerType);

View File

@@ -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<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache =
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>();
private WebArgumentResolver[] customArgumentResolvers;
private HttpMessageConverter<?>[] messageConverters =
@@ -147,10 +154,24 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
* @return the best matching method; or <code>null</code> 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<? extends Throwable> thrownExceptionType = thrownException.getClass();
final Map<Class<? extends Throwable>, Method> resolverMethods =
new LinkedHashMap<Class<? extends Throwable>, Method>();
Method handlerMethod = null;
Map<Class<? extends Throwable>, 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<Class<? extends Throwable>, Method>();
exceptionHandlerCache.put(handlerType, handlers);
}
final Map<Class<? extends Throwable>, 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;
}
/**