Browse Source

Do not cache prototype @ControllerAdvice beans

Spring Framework 5.2 introduced support for caching @ControllerAdvice
beans; however, this caching was also applied incorrectly to
non-singleton beans.

This commit addresses this regression by only caching singleton
@ControllerAdvice beans.

Closes gh-24157
pull/24160/head
yokotaso 6 years ago committed by Sam Brannen
parent
commit
d7d474f658
  1. 5
      spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java
  2. 15
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java

5
spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java

@ -54,6 +54,7 @@ public class ControllerAdviceBean implements Ordered { @@ -54,6 +54,7 @@ public class ControllerAdviceBean implements Ordered {
*/
private final Object beanOrName;
private final boolean isSingletonBean;
/**
* Reference to the resolved bean instance, potentially lazily retrieved
* via the {@code BeanFactory}.
@ -84,6 +85,7 @@ public class ControllerAdviceBean implements Ordered { @@ -84,6 +85,7 @@ public class ControllerAdviceBean implements Ordered {
this.beanType = ClassUtils.getUserClass(bean.getClass());
this.beanTypePredicate = createBeanTypePredicate(this.beanType);
this.beanFactory = null;
this.isSingletonBean = true;
}
/**
@ -115,6 +117,7 @@ public class ControllerAdviceBean implements Ordered { @@ -115,6 +117,7 @@ public class ControllerAdviceBean implements Ordered {
"] does not contain specified controller advice bean '" + beanName + "'");
this.beanOrName = beanName;
this.isSingletonBean = beanFactory.isSingleton(beanName);
this.beanType = getBeanType(beanName, beanFactory);
this.beanTypePredicate = (controllerAdvice != null ? createBeanTypePredicate(controllerAdvice) :
createBeanTypePredicate(this.beanType));
@ -191,7 +194,7 @@ public class ControllerAdviceBean implements Ordered { @@ -191,7 +194,7 @@ public class ControllerAdviceBean implements Ordered {
* will be cached, thereby avoiding repeated lookups in the {@code BeanFactory}.
*/
public Object resolveBean() {
if (this.resolvedBean == null) {
if (!this.isSingletonBean || 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);

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

@ -206,6 +206,20 @@ public class RequestMappingHandlerAdapterTests { @@ -206,6 +206,20 @@ public class RequestMappingHandlerAdapterTests {
assertThat(mav.getModel().get("attr2")).isEqualTo("gAttr2");
}
@Test
public void prototypePageControllerAdvice() 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);
assertThat(mav1.getModel().get("modelAttributeAdviceInstance")).isNotEqualTo(mav2.getModel().get("modelAttributeAdviceInstance"));
}
@Test
public void modelAttributeAdviceInParentContext() throws Exception {
StaticWebApplicationContext parent = new StaticWebApplicationContext();
@ -322,6 +336,7 @@ public class RequestMappingHandlerAdapterTests { @@ -322,6 +336,7 @@ public class RequestMappingHandlerAdapterTests {
public void addAttributes(Model model) {
model.addAttribute("attr1", "gAttr1");
model.addAttribute("attr2", "gAttr2");
model.addAttribute("modelAttributeAdviceInstance", this);
}
}

Loading…
Cancel
Save