Ignore scoped proxy targets for @ControllerAdvice beans

Prior to this commit, methods in a @ControllerAdvice bean were
registered and invoked twice if the advice was a scoped bean (e.g.,
request or session scoped). In other words, both the proxy bean and the
target bean were wrapped in ControllerAdviceBean instances.

This commit fixes this bug by modifying the findAnnotatedBeans() method
in ControllerAdviceBean so that it filters out targets of scoped
proxies.

Closes gh-24017
This commit is contained in:
Sam Brannen
2019-11-19 14:20:19 +01:00
parent 4c17314d0e
commit b4e1d48322
3 changed files with 139 additions and 16 deletions

View File

@@ -43,7 +43,6 @@ import static org.assertj.core.api.Assertions.assertThatCode;
class RequestScopedControllerAdviceIntegrationTests {
@Test // gh-23985
@SuppressWarnings({ "rawtypes", "unchecked" })
void loadContextWithRequestScopedControllerAdvice() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setServletContext(new MockServletContext());
@@ -51,17 +50,11 @@ class RequestScopedControllerAdviceIntegrationTests {
assertThatCode(context::refresh).doesNotThrowAnyException();
// Until gh-24017 is fixed, we expect the RequestScopedControllerAdvice to show up twice.
Class[] expectedTypes = { RequestScopedControllerAdvice.class, RequestScopedControllerAdvice.class };
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(context);
assertThat(adviceBeans)//
.extracting(ControllerAdviceBean::getBeanType)//
.containsExactly(expectedTypes);
assertThat(adviceBeans)//
.extracting(ControllerAdviceBean::getOrder)//
.containsExactly(42, 42);
assertThat(adviceBeans).size().isEqualTo(1);
assertThat(adviceBeans.get(0))//
.returns(RequestScopedControllerAdvice.class, ControllerAdviceBean::getBeanType)//
.returns(42, ControllerAdviceBean::getOrder);
context.close();
}