From 8ab8e4f7c2023df3486cdc256fbab09bb1aae73e Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sun, 10 Mar 2013 12:52:04 -0400 Subject: [PATCH] Make the methodParameter field of HandlerMethod final Previously the methodParameter array field was initialized lazily since it requires reflection. However, in practice the field is always used and there is not much benefit from the lazy initialization. In Spring Framework 3.2, the methodParameter field was copied when a new HandlerMethod instance (with the resolved bean) is created for performance reasons. That introduced a synchronization issue since the lazy initialization was not synchronized. Issue: SPR-10365 --- .../web/method/HandlerMethod.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index 9ed46d9cf2..aec22e4d5a 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -54,7 +54,7 @@ public class HandlerMethod { private final BeanFactory beanFactory; - private MethodParameter[] parameters; + private final MethodParameter[] parameters; private final Method bridgedMethod; @@ -69,6 +69,16 @@ public class HandlerMethod { this.beanFactory = null; this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + this.parameters = initMethodParameters(); + } + + private MethodParameter[] initMethodParameters() { + int count = this.bridgedMethod.getParameterTypes().length; + MethodParameter[] result = new MethodParameter[count]; + for (int i = 0; i < count; i++) { + result[i] = new HandlerMethodParameter(i); + } + return result; } /** @@ -82,6 +92,7 @@ public class HandlerMethod { this.beanFactory = null; this.method = bean.getClass().getMethod(methodName, parameterTypes); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + this.parameters = initMethodParameters(); } /** @@ -99,10 +110,11 @@ public class HandlerMethod { this.beanFactory = beanFactory; this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + this.parameters = initMethodParameters(); } /** - * Create an instance from another {@code HandlerMethod}. + * Copy constructor for use in sub-classes. */ protected HandlerMethod(HandlerMethod handlerMethod) { Assert.notNull(handlerMethod, "HandlerMethod is required"); @@ -113,6 +125,19 @@ public class HandlerMethod { this.parameters = handlerMethod.parameters; } + /** + * Re-create HandlerMethod with the resolved handler. + */ + private HandlerMethod(HandlerMethod handlerMethod, Object handler) { + Assert.notNull(handlerMethod, "handlerMethod is required"); + Assert.notNull(handler, "handler is required"); + this.bean = handler; + this.beanFactory = handlerMethod.beanFactory; + this.method = handlerMethod.method; + this.bridgedMethod = handlerMethod.bridgedMethod; + this.parameters = handlerMethod.parameters; + } + /** * Returns the bean for this handler method. */ @@ -150,13 +175,6 @@ public class HandlerMethod { * Returns the method parameters for this handler method. */ public MethodParameter[] getMethodParameters() { - if (this.parameters == null) { - int parameterCount = this.bridgedMethod.getParameterTypes().length; - this.parameters = new MethodParameter[parameterCount]; - for (int i = 0; i < parameterCount; i++) { - this.parameters[i] = new HandlerMethodParameter(i); - } - } return this.parameters; } @@ -201,9 +219,7 @@ public class HandlerMethod { String beanName = (String) this.bean; handler = this.beanFactory.getBean(beanName); } - HandlerMethod handlerMethod = new HandlerMethod(handler, this.method); - handlerMethod.parameters = getMethodParameters(); - return handlerMethod; + return new HandlerMethod(this, handler); } @Override