Skip to content

Commit 8ab8e4f

Browse files
committed
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
1 parent 3654a62 commit 8ab8e4f

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class HandlerMethod {
5454

5555
private final BeanFactory beanFactory;
5656

57-
private MethodParameter[] parameters;
57+
private final MethodParameter[] parameters;
5858

5959
private final Method bridgedMethod;
6060

@@ -69,6 +69,16 @@ public HandlerMethod(Object bean, Method method) {
6969
this.beanFactory = null;
7070
this.method = method;
7171
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
72+
this.parameters = initMethodParameters();
73+
}
74+
75+
private MethodParameter[] initMethodParameters() {
76+
int count = this.bridgedMethod.getParameterTypes().length;
77+
MethodParameter[] result = new MethodParameter[count];
78+
for (int i = 0; i < count; i++) {
79+
result[i] = new HandlerMethodParameter(i);
80+
}
81+
return result;
7282
}
7383

7484
/**
@@ -82,6 +92,7 @@ public HandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
8292
this.beanFactory = null;
8393
this.method = bean.getClass().getMethod(methodName, parameterTypes);
8494
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
95+
this.parameters = initMethodParameters();
8596
}
8697

8798
/**
@@ -99,10 +110,11 @@ public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
99110
this.beanFactory = beanFactory;
100111
this.method = method;
101112
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
113+
this.parameters = initMethodParameters();
102114
}
103115

104116
/**
105-
* Create an instance from another {@code HandlerMethod}.
117+
* Copy constructor for use in sub-classes.
106118
*/
107119
protected HandlerMethod(HandlerMethod handlerMethod) {
108120
Assert.notNull(handlerMethod, "HandlerMethod is required");
@@ -113,6 +125,19 @@ protected HandlerMethod(HandlerMethod handlerMethod) {
113125
this.parameters = handlerMethod.parameters;
114126
}
115127

128+
/**
129+
* Re-create HandlerMethod with the resolved handler.
130+
*/
131+
private HandlerMethod(HandlerMethod handlerMethod, Object handler) {
132+
Assert.notNull(handlerMethod, "handlerMethod is required");
133+
Assert.notNull(handler, "handler is required");
134+
this.bean = handler;
135+
this.beanFactory = handlerMethod.beanFactory;
136+
this.method = handlerMethod.method;
137+
this.bridgedMethod = handlerMethod.bridgedMethod;
138+
this.parameters = handlerMethod.parameters;
139+
}
140+
116141
/**
117142
* Returns the bean for this handler method.
118143
*/
@@ -150,13 +175,6 @@ protected Method getBridgedMethod() {
150175
* Returns the method parameters for this handler method.
151176
*/
152177
public MethodParameter[] getMethodParameters() {
153-
if (this.parameters == null) {
154-
int parameterCount = this.bridgedMethod.getParameterTypes().length;
155-
this.parameters = new MethodParameter[parameterCount];
156-
for (int i = 0; i < parameterCount; i++) {
157-
this.parameters[i] = new HandlerMethodParameter(i);
158-
}
159-
}
160178
return this.parameters;
161179
}
162180

@@ -201,9 +219,7 @@ public HandlerMethod createWithResolvedBean() {
201219
String beanName = (String) this.bean;
202220
handler = this.beanFactory.getBean(beanName);
203221
}
204-
HandlerMethod handlerMethod = new HandlerMethod(handler, this.method);
205-
handlerMethod.parameters = getMethodParameters();
206-
return handlerMethod;
222+
return new HandlerMethod(this, handler);
207223
}
208224

209225
@Override

0 commit comments

Comments
 (0)