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
master
Rossen Stoyanchev 12 years ago
parent 3654a620fb
commit 8ab8e4f7c2
  1. 40
      spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

@ -54,7 +54,7 @@ public class HandlerMethod {
private final BeanFactory beanFactory; private final BeanFactory beanFactory;
private MethodParameter[] parameters; private final MethodParameter[] parameters;
private final Method bridgedMethod; private final Method bridgedMethod;
@ -69,6 +69,16 @@ public class HandlerMethod {
this.beanFactory = null; this.beanFactory = null;
this.method = method; this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(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.beanFactory = null;
this.method = bean.getClass().getMethod(methodName, parameterTypes); this.method = bean.getClass().getMethod(methodName, parameterTypes);
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
this.parameters = initMethodParameters();
} }
/** /**
@ -99,10 +110,11 @@ public class HandlerMethod {
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
this.method = method; this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(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) { protected HandlerMethod(HandlerMethod handlerMethod) {
Assert.notNull(handlerMethod, "HandlerMethod is required"); Assert.notNull(handlerMethod, "HandlerMethod is required");
@ -113,6 +125,19 @@ public class HandlerMethod {
this.parameters = handlerMethod.parameters; 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. * Returns the bean for this handler method.
*/ */
@ -150,13 +175,6 @@ public class HandlerMethod {
* Returns the method parameters for this handler method. * Returns the method parameters for this handler method.
*/ */
public MethodParameter[] getMethodParameters() { 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; return this.parameters;
} }
@ -201,9 +219,7 @@ public class HandlerMethod {
String beanName = (String) this.bean; String beanName = (String) this.bean;
handler = this.beanFactory.getBean(beanName); handler = this.beanFactory.getBean(beanName);
} }
HandlerMethod handlerMethod = new HandlerMethod(handler, this.method); return new HandlerMethod(this, handler);
handlerMethod.parameters = getMethodParameters();
return handlerMethod;
} }
@Override @Override

Loading…
Cancel
Save