Skip to content

Commit 806e79b

Browse files
committed
Polish
1 parent e62ada8 commit 806e79b

File tree

4 files changed

+227
-245
lines changed

4 files changed

+227
-245
lines changed

spring-web/src/main/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessor.java

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,30 +38,32 @@
3838
import org.springframework.web.method.support.ModelAndViewContainer;
3939

4040
/**
41-
* Resolves method arguments annotated with {@code @ModelAttribute} and handles
42-
* return values from methods annotated with {@code @ModelAttribute}.
41+
* Resolve {@code @ModelAttribute} annotated method arguments and handle
42+
* return values from {@code @ModelAttribute} annotated methods.
4343
*
44-
* <p>Model attributes are obtained from the model or if not found possibly
45-
* created with a default constructor if it is available. Once created, the
46-
* attributed is populated with request data via data binding and also
47-
* validation may be applied if the argument is annotated with
48-
* {@code @javax.validation.Valid}.
44+
* <p>Model attributes are obtained from the model or created with a default
45+
* constructor (and then added to the model). Once created the attribute is
46+
* populated via data binding to Servlet request parameters. Validation may be
47+
* applied if the argument is annotated with {@code @javax.validation.Valid}.
48+
* or {@link @Validated}.
4949
*
50-
* <p>When this handler is created with {@code annotationNotRequired=true},
50+
* <p>When this handler is created with {@code annotationNotRequired=true}
5151
* any non-simple type argument and return value is regarded as a model
5252
* attribute with or without the presence of an {@code @ModelAttribute}.
5353
*
5454
* @author Rossen Stoyanchev
5555
* @since 3.1
5656
*/
57-
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
57+
public class ModelAttributeMethodProcessor
58+
implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
5859

5960
protected final Log logger = LogFactory.getLog(getClass());
6061

6162
private final boolean annotationNotRequired;
6263

6364

6465
/**
66+
* Class constructor.
6567
* @param annotationNotRequired if "true", non-simple method arguments and
6668
* return values are considered model attributes with or without a
6769
* {@code @ModelAttribute} annotation.
@@ -72,20 +74,14 @@ public ModelAttributeMethodProcessor(boolean annotationNotRequired) {
7274

7375

7476
/**
75-
* Returns {@code true} if the parameter is annotated with {@link ModelAttribute}
76-
* or in default resolution mode, and also if it is not a simple type.
77+
* Returns {@code true} if the parameter is annotated with
78+
* {@link ModelAttribute} or, if in default resolution mode, for any
79+
* method parameter that is not a simple type.
7780
*/
7881
@Override
7982
public boolean supportsParameter(MethodParameter parameter) {
80-
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
81-
return true;
82-
}
83-
else if (this.annotationNotRequired) {
84-
return !BeanUtils.isSimpleProperty(parameter.getParameterType());
85-
}
86-
else {
87-
return false;
88-
}
83+
return (parameter.hasParameterAnnotation(ModelAttribute.class) ||
84+
(this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType())));
8985
}
9086

9187
/**
@@ -102,8 +98,8 @@ public final Object resolveArgument(MethodParameter parameter, ModelAndViewConta
10298
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
10399

104100
String name = ModelFactory.getNameForParameter(parameter);
105-
Object attribute = (mavContainer.containsAttribute(name) ?
106-
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, webRequest));
101+
Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) :
102+
createAttribute(name, parameter, binderFactory, webRequest));
107103

108104
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
109105
if (binder.getTarget() != null) {
@@ -182,19 +178,13 @@ protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter
182178

183179
/**
184180
* Return {@code true} if there is a method-level {@code @ModelAttribute}
185-
* or if it is a non-simple type when {@code annotationNotRequired=true}.
181+
* or, in default resolution mode, for any return value type that is not
182+
* a simple type.
186183
*/
187184
@Override
188185
public boolean supportsReturnType(MethodParameter returnType) {
189-
if (returnType.getMethodAnnotation(ModelAttribute.class) != null) {
190-
return true;
191-
}
192-
else if (this.annotationNotRequired) {
193-
return !BeanUtils.isSimpleProperty(returnType.getParameterType());
194-
}
195-
else {
196-
return false;
197-
}
186+
return (returnType.getMethodAnnotation(ModelAttribute.class) != null ||
187+
this.annotationNotRequired && !BeanUtils.isSimpleProperty(returnType.getParameterType()));
198188
}
199189

200190
/**

spring-web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,14 +45,15 @@
4545
import org.springframework.web.method.support.ModelAndViewContainer;
4646

4747
/**
48-
* Provides methods to initialize the {@link Model} before controller method
49-
* invocation and to update it afterwards.
48+
* Assist with initialization of the {@link Model} before controller method
49+
* invocation and with updates to it after the invocation.
5050
*
51-
* <p>On initialization, the model is populated with attributes from the session
52-
* and by invoking methods annotated with {@code @ModelAttribute}.
51+
* <p>On initialization the model is populated with attributes temporarily
52+
* stored in the session and through the invocation of {@code @ModelAttribute}
53+
* methods.
5354
*
54-
* <p>On update, model attributes are synchronized with the session and also
55-
* {@link BindingResult} attributes are added where missing.
55+
* <p>On update model attributes are synchronized with the session and also
56+
* {@link BindingResult} attributes are added if missing.
5657
*
5758
* @author Rossen Stoyanchev
5859
* @since 3.1
@@ -61,6 +62,7 @@ public final class ModelFactory {
6162

6263
private static final Log logger = LogFactory.getLog(ModelFactory.class);
6364

65+
6466
private final List<ModelMethod> modelMethods = new ArrayList<ModelMethod>();
6567

6668
private final WebDataBinderFactory dataBinderFactory;
@@ -70,22 +72,23 @@ public final class ModelFactory {
7072

7173
/**
7274
* Create a new instance with the given {@code @ModelAttribute} methods.
73-
* @param invocableMethods the {@code @ModelAttribute} methods to invoke
74-
* @param dataBinderFactory for preparation of {@link BindingResult} attributes
75-
* @param sessionAttributesHandler for access to session attributes
75+
* @param handlerMethods the {@code @ModelAttribute} methods to invoke
76+
* @param binderFactory for preparation of {@link BindingResult} attributes
77+
* @param attributeHandler for access to session attributes
7678
*/
77-
public ModelFactory(List<InvocableHandlerMethod> invocableMethods, WebDataBinderFactory dataBinderFactory,
78-
SessionAttributesHandler sessionAttributesHandler) {
79+
public ModelFactory(List<InvocableHandlerMethod> handlerMethods,
80+
WebDataBinderFactory binderFactory, SessionAttributesHandler attributeHandler) {
7981

80-
if (invocableMethods != null) {
81-
for (InvocableHandlerMethod method : invocableMethods) {
82-
this.modelMethods.add(new ModelMethod(method));
82+
if (handlerMethods != null) {
83+
for (InvocableHandlerMethod handlerMethod : handlerMethods) {
84+
this.modelMethods.add(new ModelMethod(handlerMethod));
8385
}
8486
}
85-
this.dataBinderFactory = dataBinderFactory;
86-
this.sessionAttributesHandler = sessionAttributesHandler;
87+
this.dataBinderFactory = binderFactory;
88+
this.sessionAttributesHandler = attributeHandler;
8789
}
8890

91+
8992
/**
9093
* Populate the model in the following order:
9194
* <ol>
@@ -96,25 +99,26 @@ public ModelFactory(List<InvocableHandlerMethod> invocableMethods, WebDataBinder
9699
* an exception if necessary.
97100
* </ol>
98101
* @param request the current request
99-
* @param mavContainer a container with the model to be initialized
102+
* @param container a container with the model to be initialized
100103
* @param handlerMethod the method for which the model is initialized
101104
* @throws Exception may arise from {@code @ModelAttribute} methods
102105
*/
103-
public void initModel(NativeWebRequest request, ModelAndViewContainer mavContainer, HandlerMethod handlerMethod)
104-
throws Exception {
106+
public void initModel(NativeWebRequest request, ModelAndViewContainer container,
107+
HandlerMethod handlerMethod) throws Exception {
105108

106109
Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
107-
mavContainer.mergeAttributes(sessionAttributes);
110+
container.mergeAttributes(sessionAttributes);
108111

109-
invokeModelAttributeMethods(request, mavContainer);
112+
invokeModelAttributeMethods(request, container);
110113

111114
for (String name : findSessionAttributeArguments(handlerMethod)) {
112-
if (!mavContainer.containsAttribute(name)) {
115+
if (!container.containsAttribute(name)) {
113116
Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
114117
if (value == null) {
115-
throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
118+
throw new HttpSessionRequiredException(
119+
"Expected session attribute '" + name + "'");
116120
}
117-
mavContainer.addAttribute(name, value);
121+
container.addAttribute(name, value);
118122
}
119123
}
120124
}
@@ -123,30 +127,31 @@ public void initModel(NativeWebRequest request, ModelAndViewContainer mavContain
123127
* Invoke model attribute methods to populate the model.
124128
* Attributes are added only if not already present in the model.
125129
*/
126-
private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer mavContainer)
127-
throws Exception {
130+
private void invokeModelAttributeMethods(NativeWebRequest request,
131+
ModelAndViewContainer container) throws Exception {
128132

129133
while (!this.modelMethods.isEmpty()) {
130-
InvocableHandlerMethod attrMethod = getNextModelMethod(mavContainer).getHandlerMethod();
131-
String modelName = attrMethod.getMethodAnnotation(ModelAttribute.class).value();
132-
if (mavContainer.containsAttribute(modelName)) {
134+
InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
135+
ModelAttribute annot = modelMethod.getMethodAnnotation(ModelAttribute.class);
136+
String modelName = annot.value();
137+
if (container.containsAttribute(modelName)) {
133138
continue;
134139
}
135140

136-
Object returnValue = attrMethod.invokeForRequest(request, mavContainer);
141+
Object returnValue = modelMethod.invokeForRequest(request, container);
137142

138-
if (!attrMethod.isVoid()){
139-
String returnValueName = getNameForReturnValue(returnValue, attrMethod.getReturnType());
140-
if (!mavContainer.containsAttribute(returnValueName)) {
141-
mavContainer.addAttribute(returnValueName, returnValue);
143+
if (!modelMethod.isVoid()){
144+
String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
145+
if (!container.containsAttribute(returnValueName)) {
146+
container.addAttribute(returnValueName, returnValue);
142147
}
143148
}
144149
}
145150
}
146151

147-
private ModelMethod getNextModelMethod(ModelAndViewContainer mavContainer) {
152+
private ModelMethod getNextModelMethod(ModelAndViewContainer container) {
148153
for (ModelMethod modelMethod : this.modelMethods) {
149-
if (modelMethod.checkDependencies(mavContainer)) {
154+
if (modelMethod.checkDependencies(container)) {
150155
if (logger.isTraceEnabled()) {
151156
logger.trace("Selected @ModelAttribute method " + modelMethod);
152157
}
@@ -157,7 +162,7 @@ private ModelMethod getNextModelMethod(ModelAndViewContainer mavContainer) {
157162
ModelMethod modelMethod = this.modelMethods.get(0);
158163
if (logger.isTraceEnabled()) {
159164
logger.trace("Selected @ModelAttribute method (not present: " +
160-
modelMethod.getUnresolvedDependencies(mavContainer)+ ") " + modelMethod);
165+
modelMethod.getUnresolvedDependencies(container)+ ") " + modelMethod);
161166
}
162167
this.modelMethods.remove(modelMethod);
163168
return modelMethod;
@@ -171,7 +176,8 @@ private List<String> findSessionAttributeArguments(HandlerMethod handlerMethod)
171176
for (MethodParameter parameter : handlerMethod.getMethodParameters()) {
172177
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
173178
String name = getNameForParameter(parameter);
174-
if (this.sessionAttributesHandler.isHandlerSessionAttribute(name, parameter.getParameterType())) {
179+
Class<?> paramType = parameter.getParameterType();
180+
if (this.sessionAttributesHandler.isHandlerSessionAttribute(name, paramType)) {
175181
result.add(name);
176182
}
177183
}
@@ -189,8 +195,8 @@ private List<String> findSessionAttributeArguments(HandlerMethod handlerMethod)
189195
*/
190196
public static String getNameForParameter(MethodParameter parameter) {
191197
ModelAttribute annot = parameter.getParameterAnnotation(ModelAttribute.class);
192-
String attrName = (annot != null) ? annot.value() : null;
193-
return StringUtils.hasText(attrName) ? attrName : Conventions.getVariableNameForParameter(parameter);
198+
String name = (annot != null) ? annot.value() : null;
199+
return StringUtils.hasText(name) ? name : Conventions.getVariableNameForParameter(parameter);
194200
}
195201

196202
/**
@@ -211,7 +217,8 @@ public static String getNameForReturnValue(Object returnValue, MethodParameter r
211217
}
212218
else {
213219
Method method = returnType.getMethod();
214-
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, returnType.getContainingClass());
220+
Class<?> containingClass = returnType.getContainingClass();
221+
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, containingClass);
215222
return Conventions.getVariableNameForReturnType(method, resolvedType, returnValue);
216223
}
217224
}
@@ -220,18 +227,18 @@ public static String getNameForReturnValue(Object returnValue, MethodParameter r
220227
* Promote model attributes listed as {@code @SessionAttributes} to the session.
221228
* Add {@link BindingResult} attributes where necessary.
222229
* @param request the current request
223-
* @param mavContainer contains the model to update
230+
* @param container contains the model to update
224231
* @throws Exception if creating BindingResult attributes fails
225232
*/
226-
public void updateModel(NativeWebRequest request, ModelAndViewContainer mavContainer) throws Exception {
227-
ModelMap defaultModel = mavContainer.getDefaultModel();
228-
if (mavContainer.getSessionStatus().isComplete()){
233+
public void updateModel(NativeWebRequest request, ModelAndViewContainer container) throws Exception {
234+
ModelMap defaultModel = container.getDefaultModel();
235+
if (container.getSessionStatus().isComplete()){
229236
this.sessionAttributesHandler.cleanupAttributes(request);
230237
}
231238
else {
232239
this.sessionAttributesHandler.storeAttributes(request, defaultModel);
233240
}
234-
if (!mavContainer.isRequestHandled() && mavContainer.getModel() == defaultModel) {
241+
if (!container.isRequestHandled() && container.getModel() == defaultModel) {
235242
updateBindingResult(request, defaultModel);
236243
}
237244
}
@@ -248,7 +255,7 @@ private void updateBindingResult(NativeWebRequest request, ModelMap model) throw
248255
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + name;
249256

250257
if (!model.containsAttribute(bindingResultKey)) {
251-
WebDataBinder dataBinder = dataBinderFactory.createBinder(request, value, name);
258+
WebDataBinder dataBinder = this.dataBinderFactory.createBinder(request, value, name);
252259
model.put(bindingResultKey, dataBinder.getBindingResult());
253260
}
254261
}

0 commit comments

Comments
 (0)