From 78fcd28389aefc6a767121fd637d9df97562fbed Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 10 May 2013 10:42:42 -0400 Subject: [PATCH] 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 --- .../RequestMappingHandlerAdapter.java | 18 ++++++++++-------- .../RequestMappingHandlerAdapterTests.java | 11 +++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java index 848e912703..83c205360b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java @@ -772,16 +772,17 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i this.modelAttributeCache.put(handlerType, methods); } List attrMethods = new ArrayList(); - for (Method method : methods) { - Object bean = handlerMethod.getBean(); - attrMethods.add(createModelAttributeMethod(binderFactory, bean, method)); - } + // Global methods first for (Entry> entry : this.modelAttributeAdviceCache.entrySet()) { Object bean = entry.getKey().resolveBean(); for (Method method : entry.getValue()) { attrMethods.add(createModelAttributeMethod(binderFactory, bean, method)); } } + for (Method method : methods) { + Object bean = handlerMethod.getBean(); + attrMethods.add(createModelAttributeMethod(binderFactory, bean, method)); + } return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler); } @@ -801,16 +802,17 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i this.initBinderCache.put(handlerType, methods); } List initBinderMethods = new ArrayList(); - for (Method method : methods) { - Object bean = handlerMethod.getBean(); - initBinderMethods.add(createInitBinderMethod(bean, method)); - } + // Global methods first for (Entry> entry : this.initBinderAdviceCache .entrySet()) { Object bean = entry.getKey().resolveBean(); for (Method method : entry.getValue()) { initBinderMethods.add(createInitBinderMethod(bean, method)); } } + for (Method method : methods) { + Object bean = handlerMethod.getBean(); + initBinderMethods.add(createInitBinderMethod(bean, method)); + } return createDataBinderFactory(initBinderMethods); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java index 2e4c7fb7fb..629b7ea631 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java @@ -181,7 +181,8 @@ public class RequestMappingHandlerAdapterTests { this.handlerAdapter.afterPropertiesSet(); ModelAndView mav = this.handlerAdapter.handle(this.request, this.response, handlerMethod); - assertEquals("globalAttrValue", mav.getModel().get("globalAttr")); + assertEquals("lAttr1", mav.getModel().get("attr1")); + assertEquals("gAttr2", mav.getModel().get("attr2")); } @@ -200,6 +201,11 @@ public class RequestMappingHandlerAdapterTests { @SuppressWarnings("unused") private static class SimpleController { + @ModelAttribute + public void addAttributes(Model model) { + model.addAttribute("attr1", "lAttr1"); + } + public String handle() { return null; } @@ -227,7 +233,8 @@ public class RequestMappingHandlerAdapterTests { @ModelAttribute public void addAttributes(Model model) { - model.addAttribute("globalAttr", "globalAttrValue"); + model.addAttribute("attr1", "gAttr1"); + model.addAttribute("attr2", "gAttr2"); } }