Skip to content

Commit 5986f88

Browse files
committed
HandlerMethod evaluates ResponseStatus annotation for early caching
Issue: SPR-15227
1 parent ff03b4a commit 5986f88

File tree

4 files changed

+82
-81
lines changed

4 files changed

+82
-81
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class HandlerMethod {
6464

6565
private final MethodParameter[] parameters;
6666

67-
private final HandlerMethod resolvedFromHandlerMethod;
67+
private HandlerMethod resolvedFromHandlerMethod;
6868

6969

7070
/**
@@ -79,7 +79,6 @@ public HandlerMethod(Object bean, Method method) {
7979
this.method = method;
8080
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
8181
this.parameters = initMethodParameters();
82-
this.resolvedFromHandlerMethod = null;
8382
}
8483

8584
/**
@@ -95,7 +94,6 @@ public HandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
9594
this.method = bean.getClass().getMethod(methodName, parameterTypes);
9695
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method);
9796
this.parameters = initMethodParameters();
98-
this.resolvedFromHandlerMethod = null;
9997
}
10098

10199
/**
@@ -113,7 +111,6 @@ public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
113111
this.method = method;
114112
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
115113
this.parameters = initMethodParameters();
116-
this.resolvedFromHandlerMethod = null;
117114
}
118115

119116
/**
@@ -158,14 +155,14 @@ private MethodParameter[] initMethodParameters() {
158155
}
159156

160157
/**
161-
* Returns the bean for this handler method.
158+
* Return the bean for this handler method.
162159
*/
163160
public Object getBean() {
164161
return this.bean;
165162
}
166163

167164
/**
168-
* Returns the method for this handler method.
165+
* Return the method for this handler method.
169166
*/
170167
public Method getMethod() {
171168
return this.method;
@@ -189,21 +186,12 @@ protected Method getBridgedMethod() {
189186
}
190187

191188
/**
192-
* Returns the method parameters for this handler method.
189+
* Return the method parameters for this handler method.
193190
*/
194191
public MethodParameter[] getMethodParameters() {
195192
return this.parameters;
196193
}
197194

198-
/**
199-
* Return the HandlerMethod from which this HandlerMethod instance was
200-
* resolved via {@link #createWithResolvedBean()}.
201-
* @since 4.3
202-
*/
203-
public HandlerMethod getResolvedFromHandlerMethod() {
204-
return this.resolvedFromHandlerMethod;
205-
}
206-
207195
/**
208196
* Return the HandlerMethod return type.
209197
*/
@@ -219,14 +207,14 @@ public MethodParameter getReturnValueType(Object returnValue) {
219207
}
220208

221209
/**
222-
* Returns {@code true} if the method return type is void, {@code false} otherwise.
210+
* Return {@code true} if the method return type is void, {@code false} otherwise.
223211
*/
224212
public boolean isVoid() {
225213
return Void.TYPE.equals(getReturnType().getParameterType());
226214
}
227215

228216
/**
229-
* Returns a single annotation on the underlying method traversing its super methods
217+
* Return a single annotation on the underlying method traversing its super methods
230218
* if no annotation can be found on the given method itself.
231219
* <p>Also supports <em>merged</em> composed annotations with attribute
232220
* overrides as of Spring Framework 4.3.
@@ -248,6 +236,15 @@ public <A extends Annotation> boolean hasMethodAnnotation(Class<A> annotationTyp
248236
return AnnotatedElementUtils.hasAnnotation(this.method, annotationType);
249237
}
250238

239+
/**
240+
* Return the HandlerMethod from which this HandlerMethod instance was
241+
* resolved via {@link #createWithResolvedBean()}.
242+
* @since 4.3
243+
*/
244+
public HandlerMethod getResolvedFromHandlerMethod() {
245+
return this.resolvedFromHandlerMethod;
246+
}
247+
251248
/**
252249
* If the provided instance contains a bean name rather than an object instance,
253250
* the bean name is resolved before a {@link HandlerMethod} is created and returned.

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

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828
import org.springframework.core.MethodParameter;
2929
import org.springframework.core.annotation.AnnotatedElementUtils;
3030
import org.springframework.core.annotation.SynthesizingMethodParameter;
31+
import org.springframework.http.HttpStatus;
3132
import org.springframework.util.Assert;
3233
import org.springframework.util.ClassUtils;
34+
import org.springframework.web.bind.annotation.ResponseStatus;
3335

3436
/**
3537
* Encapsulates information about a handler method consisting of a
@@ -65,7 +67,11 @@ public class HandlerMethod {
6567

6668
private final MethodParameter[] parameters;
6769

68-
private final HandlerMethod resolvedFromHandlerMethod;
70+
private HttpStatus responseStatus;
71+
72+
private String responseStatusReason;
73+
74+
private HandlerMethod resolvedFromHandlerMethod;
6975

7076

7177
/**
@@ -80,7 +86,7 @@ public HandlerMethod(Object bean, Method method) {
8086
this.method = method;
8187
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
8288
this.parameters = initMethodParameters();
83-
this.resolvedFromHandlerMethod = null;
89+
evaluateResponseStatus();
8490
}
8591

8692
/**
@@ -96,7 +102,7 @@ public HandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
96102
this.method = bean.getClass().getMethod(methodName, parameterTypes);
97103
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method);
98104
this.parameters = initMethodParameters();
99-
this.resolvedFromHandlerMethod = null;
105+
evaluateResponseStatus();
100106
}
101107

102108
/**
@@ -114,7 +120,7 @@ public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
114120
this.method = method;
115121
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
116122
this.parameters = initMethodParameters();
117-
this.resolvedFromHandlerMethod = null;
123+
evaluateResponseStatus();
118124
}
119125

120126
/**
@@ -128,6 +134,8 @@ protected HandlerMethod(HandlerMethod handlerMethod) {
128134
this.method = handlerMethod.method;
129135
this.bridgedMethod = handlerMethod.bridgedMethod;
130136
this.parameters = handlerMethod.parameters;
137+
this.responseStatus = handlerMethod.responseStatus;
138+
this.responseStatusReason = handlerMethod.responseStatusReason;
131139
this.resolvedFromHandlerMethod = handlerMethod.resolvedFromHandlerMethod;
132140
}
133141

@@ -143,6 +151,8 @@ private HandlerMethod(HandlerMethod handlerMethod, Object handler) {
143151
this.method = handlerMethod.method;
144152
this.bridgedMethod = handlerMethod.bridgedMethod;
145153
this.parameters = handlerMethod.parameters;
154+
this.responseStatus = handlerMethod.responseStatus;
155+
this.responseStatusReason = handlerMethod.responseStatusReason;
146156
this.resolvedFromHandlerMethod = handlerMethod;
147157
}
148158

@@ -158,15 +168,27 @@ private MethodParameter[] initMethodParameters() {
158168
return result;
159169
}
160170

171+
private void evaluateResponseStatus() {
172+
ResponseStatus annotation = getMethodAnnotation(ResponseStatus.class);
173+
if (annotation == null) {
174+
annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class);
175+
}
176+
if (annotation != null) {
177+
this.responseStatus = annotation.code();
178+
this.responseStatusReason = annotation.reason();
179+
}
180+
}
181+
182+
161183
/**
162-
* Returns the bean for this handler method.
184+
* Return the bean for this handler method.
163185
*/
164186
public Object getBean() {
165187
return this.bean;
166188
}
167189

168190
/**
169-
* Returns the method for this handler method.
191+
* Return the method for this handler method.
170192
*/
171193
public Method getMethod() {
172194
return this.method;
@@ -190,18 +212,28 @@ protected Method getBridgedMethod() {
190212
}
191213

192214
/**
193-
* Returns the method parameters for this handler method.
215+
* Return the method parameters for this handler method.
194216
*/
195217
public MethodParameter[] getMethodParameters() {
196218
return this.parameters;
197219
}
198220

199221
/**
200-
* Return the HandlerMethod from which this HandlerMethod instance was
201-
* resolved via {@link #createWithResolvedBean()}.
222+
* Return the specified response status, if any.
223+
* @since 4.3.8
224+
* @see ResponseStatus#code()
202225
*/
203-
public HandlerMethod getResolvedFromHandlerMethod() {
204-
return this.resolvedFromHandlerMethod;
226+
protected HttpStatus getResponseStatus() {
227+
return this.responseStatus;
228+
}
229+
230+
/**
231+
* Return the associated response status reason, if any.
232+
* @since 4.3.8
233+
* @see ResponseStatus#reason()
234+
*/
235+
protected String getResponseStatusReason() {
236+
return this.responseStatusReason;
205237
}
206238

207239
/**
@@ -219,14 +251,14 @@ public MethodParameter getReturnValueType(Object returnValue) {
219251
}
220252

221253
/**
222-
* Returns {@code true} if the method return type is void, {@code false} otherwise.
254+
* Return {@code true} if the method return type is void, {@code false} otherwise.
223255
*/
224256
public boolean isVoid() {
225257
return Void.TYPE.equals(getReturnType().getParameterType());
226258
}
227259

228260
/**
229-
* Returns a single annotation on the underlying method traversing its super methods
261+
* Return a single annotation on the underlying method traversing its super methods
230262
* if no annotation can be found on the given method itself.
231263
* <p>Also supports <em>merged</em> composed annotations with attribute
232264
* overrides as of Spring Framework 4.2.2.
@@ -248,6 +280,14 @@ public <A extends Annotation> boolean hasMethodAnnotation(Class<A> annotationTyp
248280
return AnnotatedElementUtils.hasAnnotation(this.method, annotationType);
249281
}
250282

283+
/**
284+
* Return the HandlerMethod from which this HandlerMethod instance was
285+
* resolved via {@link #createWithResolvedBean()}.
286+
*/
287+
public HandlerMethod getResolvedFromHandlerMethod() {
288+
return this.resolvedFromHandlerMethod;
289+
}
290+
251291
/**
252292
* If the provided instance contains a bean name rather than an object instance,
253293
* the bean name is resolved before a {@link HandlerMethod} is created and returned.

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@
3131
import org.springframework.core.DefaultParameterNameDiscoverer;
3232
import org.springframework.core.MethodParameter;
3333
import org.springframework.core.ParameterNameDiscoverer;
34-
import org.springframework.core.annotation.AnnotatedElementUtils;
3534
import org.springframework.http.HttpStatus;
3635
import org.springframework.util.ClassUtils;
3736
import org.springframework.util.ObjectUtils;
3837
import org.springframework.util.ReflectionUtils;
39-
import org.springframework.web.bind.annotation.ResponseStatus;
4038
import org.springframework.web.method.HandlerMethod;
4139
import org.springframework.web.reactive.BindingContext;
4240
import org.springframework.web.reactive.HandlerResult;
@@ -57,8 +55,6 @@ public class InvocableHandlerMethod extends HandlerMethod {
5755

5856
private static final Object NO_ARG_VALUE = new Object();
5957

60-
private HttpStatus responseStatus;
61-
6258

6359
private List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
6460

@@ -67,23 +63,12 @@ public class InvocableHandlerMethod extends HandlerMethod {
6763

6864
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
6965
super(handlerMethod);
70-
initResponseStatus();
7166
}
7267

7368
public InvocableHandlerMethod(Object bean, Method method) {
7469
super(bean, method);
75-
initResponseStatus();
7670
}
7771

78-
private void initResponseStatus() {
79-
ResponseStatus annotation = getMethodAnnotation(ResponseStatus.class);
80-
if (annotation == null) {
81-
annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class);
82-
}
83-
if (annotation != null) {
84-
this.responseStatus = annotation.code();
85-
}
86-
}
8772

8873
/**
8974
* Configure the argument resolvers to use to use for resolving method
@@ -132,8 +117,9 @@ public Mono<HandlerResult> invoke(ServerWebExchange exchange, BindingContext bin
132117
try {
133118
Object value = doInvoke(args);
134119
HandlerResult result = new HandlerResult(this, value, getReturnType(), bindingContext);
135-
if (this.responseStatus != null) {
136-
exchange.getResponse().setStatusCode(this.responseStatus);
120+
HttpStatus status = getResponseStatus();
121+
if (status != null) {
122+
exchange.getResponse().setStatusCode(status);
137123
}
138124
return Mono.just(result);
139125
}

0 commit comments

Comments
 (0)