Skip to content

Commit 532a7a3

Browse files
committed
Invoke global, then local @InitBinder/@ModelAttribute
@InitBinder and @ModelAttribute methods in @ControllerAdvice classes are now invoked first, allowing any such methods in the @controller class to override them. Issue: SPR-10419
1 parent b2d416f commit 532a7a3

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -772,16 +772,17 @@ private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderF
772772
this.modelAttributeCache.put(handlerType, methods);
773773
}
774774
List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
775-
for (Method method : methods) {
776-
Object bean = handlerMethod.getBean();
777-
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
778-
}
775+
// Global methods first
779776
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
780777
Object bean = entry.getKey().resolveBean();
781778
for (Method method : entry.getValue()) {
782779
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
783780
}
784781
}
782+
for (Method method : methods) {
783+
Object bean = handlerMethod.getBean();
784+
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
785+
}
785786
return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
786787
}
787788

@@ -801,16 +802,17 @@ private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) t
801802
this.initBinderCache.put(handlerType, methods);
802803
}
803804
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
804-
for (Method method : methods) {
805-
Object bean = handlerMethod.getBean();
806-
initBinderMethods.add(createInitBinderMethod(bean, method));
807-
}
805+
// Global methods first
808806
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache .entrySet()) {
809807
Object bean = entry.getKey().resolveBean();
810808
for (Method method : entry.getValue()) {
811809
initBinderMethods.add(createInitBinderMethod(bean, method));
812810
}
813811
}
812+
for (Method method : methods) {
813+
Object bean = handlerMethod.getBean();
814+
initBinderMethods.add(createInitBinderMethod(bean, method));
815+
}
814816
return createDataBinderFactory(initBinderMethods);
815817
}
816818

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ public void modelAttributeAdvice() throws Exception {
181181
this.handlerAdapter.afterPropertiesSet();
182182
ModelAndView mav = this.handlerAdapter.handle(this.request, this.response, handlerMethod);
183183

184-
assertEquals("globalAttrValue", mav.getModel().get("globalAttr"));
184+
assertEquals("lAttr1", mav.getModel().get("attr1"));
185+
assertEquals("gAttr2", mav.getModel().get("attr2"));
185186
}
186187

187188

@@ -200,6 +201,11 @@ private void assertMethodProcessorCount(int resolverCount, int initBinderResolve
200201
@SuppressWarnings("unused")
201202
private static class SimpleController {
202203

204+
@ModelAttribute
205+
public void addAttributes(Model model) {
206+
model.addAttribute("attr1", "lAttr1");
207+
}
208+
203209
public String handle() {
204210
return null;
205211
}
@@ -227,7 +233,8 @@ private static class ModelAttributeAdvice {
227233

228234
@ModelAttribute
229235
public void addAttributes(Model model) {
230-
model.addAttribute("globalAttr", "globalAttrValue");
236+
model.addAttribute("attr1", "gAttr1");
237+
model.addAttribute("attr2", "gAttr2");
231238
}
232239
}
233240

0 commit comments

Comments
 (0)