From 291522a261160838dbd634cac03049a89991069c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 23 Nov 2018 16:55:43 +0000 Subject: [PATCH] Avoid duplicate scope registration Closes gh-14990 --- .../EmbeddedWebApplicationContext.java | 19 ++++++++---- .../EmbeddedWebApplicationContextTests.java | 31 ++++++++++++++++++- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java index 1611428d824..82f9bc6fd76 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,7 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.context.support.ServletContextAwareProcessor; import org.springframework.web.context.support.ServletContextResource; +import org.springframework.web.context.support.ServletContextScope; import org.springframework.web.context.support.WebApplicationContextUtils; /** @@ -114,7 +115,7 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext beanFactory.addBeanPostProcessor( new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); - registerWebApplicationScopes(null); + registerWebApplicationScopes(); } @Override @@ -218,7 +219,7 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext private void selfInitialize(ServletContext servletContext) throws ServletException { prepareEmbeddedWebApplicationContext(servletContext); - registerWebApplicationScopes(servletContext); + registerApplicationScope(servletContext); WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext); for (ServletContextInitializer beans : getServletContextInitializerBeans()) { @@ -226,11 +227,17 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext } } - private void registerWebApplicationScopes(ServletContext servletContext) { + private void registerApplicationScope(ServletContext servletContext) { + ServletContextScope appScope = new ServletContextScope(servletContext); + getBeanFactory().registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); + // Register as ServletContext attribute, for ContextCleanupListener to detect it. + servletContext.setAttribute(ServletContextScope.class.getName(), appScope); + } + + private void registerWebApplicationScopes() { ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes( getBeanFactory()); - WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory(), - servletContext); + WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory()); existingScopes.restore(); } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java index 5fa0bc259fb..22b9fc4d9ef 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,7 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.Scope; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.boot.testutil.InternalOutputCapture; import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletContextInitializer; @@ -96,6 +97,9 @@ public class EmbeddedWebApplicationContextTests { @Rule public ExpectedException thrown = ExpectedException.none(); + @Rule + public InternalOutputCapture output = new InternalOutputCapture(); + private EmbeddedWebApplicationContext context; @Captor @@ -489,6 +493,7 @@ public class EmbeddedWebApplicationContextTests { @Test public void servletRequestCanBeInjectedEarly() throws Exception { // gh-14990 + int initialOutputLength = this.output.toString().length(); addEmbeddedServletContainerFactoryBean(); RootBeanDefinition beanDefinition = new RootBeanDefinition( WithAutowiredServletRequest.class); @@ -507,6 +512,16 @@ public class EmbeddedWebApplicationContextTests { }); this.context.refresh(); + String output = this.output.toString().substring(initialOutputLength); + assertThat(output).doesNotContain("Replacing scope"); + } + + @Test + public void webApplicationScopeIsRegistered() throws Exception { + addEmbeddedServletContainerFactoryBean(); + this.context.refresh(); + assertThat(this.context.getBeanFactory() + .getRegisteredScope(WebApplicationContext.SCOPE_APPLICATION)).isNotNull(); } private void addEmbeddedServletContainerFactoryBean() { @@ -575,4 +590,18 @@ public class EmbeddedWebApplicationContextTests { } + protected static class WithAutowiredServletContext { + + private final ServletContext context; + + public WithAutowiredServletContext(ServletContext context) { + this.context = context; + } + + public ServletContext getContext() { + return this.context; + } + + } + }