diff --git a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java index fbf7318c96..dc424a8627 100644 --- a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java +++ b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java @@ -54,7 +54,8 @@ public class ControllerAdviceBean implements Ordered { */ private final Object beanOrName; - private final boolean isSingletonBean; + private final boolean isSingleton; + /** * Reference to the resolved bean instance, potentially lazily retrieved * via the {@code BeanFactory}. @@ -81,11 +82,11 @@ public class ControllerAdviceBean implements Ordered { public ControllerAdviceBean(Object bean) { Assert.notNull(bean, "Bean must not be null"); this.beanOrName = bean; + this.isSingleton = true; this.resolvedBean = bean; this.beanType = ClassUtils.getUserClass(bean.getClass()); this.beanTypePredicate = createBeanTypePredicate(this.beanType); this.beanFactory = null; - this.isSingletonBean = true; } /** @@ -117,7 +118,7 @@ public class ControllerAdviceBean implements Ordered { "] does not contain specified controller advice bean '" + beanName + "'"); this.beanOrName = beanName; - this.isSingletonBean = beanFactory.isSingleton(beanName); + this.isSingleton = beanFactory.isSingleton(beanName); this.beanType = getBeanType(beanName, beanFactory); this.beanTypePredicate = (controllerAdvice != null ? createBeanTypePredicate(controllerAdvice) : createBeanTypePredicate(this.beanType)); @@ -191,13 +192,19 @@ public class ControllerAdviceBean implements Ordered { * Get the bean instance for this {@code ControllerAdviceBean}, if necessary * resolving the bean name through the {@link BeanFactory}. *

As of Spring Framework 5.2, once the bean instance has been resolved it - * will be cached, thereby avoiding repeated lookups in the {@code BeanFactory}. + * will be cached if it is a singleton, thereby avoiding repeated lookups in + * the {@code BeanFactory}. */ public Object resolveBean() { - if (!this.isSingletonBean || this.resolvedBean == null) { + if (this.resolvedBean == null) { // this.beanOrName must be a String representing the bean name if // this.resolvedBean is null. - this.resolvedBean = obtainBeanFactory().getBean((String) this.beanOrName); + Object resolvedBean = obtainBeanFactory().getBean((String) this.beanOrName); + // Don't cache non-singletons (e.g., prototypes). + if (!this.isSingleton) { + return resolvedBean; + } + this.resolvedBean = resolvedBean; } return this.resolvedBean; } 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 f97a39c5fd..51eb3d983b 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 @@ -207,19 +207,18 @@ public class RequestMappingHandlerAdapterTests { } @Test - public void prototypePageControllerAdvice() throws Exception { + public void prototypeControllerAdvice() throws Exception { this.webAppContext.registerPrototype("maa", ModelAttributeAdvice.class); this.webAppContext.refresh(); HandlerMethod handlerMethod = handlerMethod(new SimpleController(), "handle"); this.handlerAdapter.afterPropertiesSet(); - ModelAndView mav1 = this.handlerAdapter.handle(this.request, this.response, handlerMethod); - ModelAndView mav2 = this.handlerAdapter.handle(this.request, this.response, handlerMethod); + Map model1 = this.handlerAdapter.handle(this.request, this.response, handlerMethod).getModel(); + Map model2 = this.handlerAdapter.handle(this.request, this.response, handlerMethod).getModel(); - assertThat(mav1.getModel().get("modelAttributeAdviceInstance")).isNotEqualTo(mav2.getModel().get("modelAttributeAdviceInstance")); + assertThat(model1.get("instance")).isNotSameAs(model2.get("instance")); } - @Test public void modelAttributeAdviceInParentContext() throws Exception { StaticWebApplicationContext parent = new StaticWebApplicationContext(); @@ -336,7 +335,7 @@ public class RequestMappingHandlerAdapterTests { public void addAttributes(Model model) { model.addAttribute("attr1", "gAttr1"); model.addAttribute("attr2", "gAttr2"); - model.addAttribute("modelAttributeAdviceInstance", this); + model.addAttribute("instance", this); } }