Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit 8ab8e4f7c2023df3486cdc256fbab09bb1aae73e 1 parent 3654a62
@rstoyanchev rstoyanchev authored
View
40 spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
@@ -54,7 +54,7 @@
private final BeanFactory beanFactory;
- private MethodParameter[] parameters;
+ private final MethodParameter[] parameters;
private final Method bridgedMethod;
@@ -69,6 +69,16 @@ public HandlerMethod(Object bean, Method method) {
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 HandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
this.beanFactory = null;
this.method = bean.getClass().getMethod(methodName, parameterTypes);
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
+ this.parameters = initMethodParameters();
}
/**
@@ -99,10 +110,11 @@ public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
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");
@@ -114,6 +126,19 @@ protected HandlerMethod(HandlerMethod handlerMethod) {
}
/**
+ * 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.
*/
public Object getBean() {
@@ -150,13 +175,6 @@ protected Method getBridgedMethod() {
* 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 HandlerMethod createWithResolvedBean() {
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
Please sign in to comment.
Something went wrong with that request. Please try again.