Skip to content

Commit b60da5f

Browse files
committed
Allow early ServletRequest Autowiring
Update `EmbeddedWebApplicationContext` so that Servlet related resolvable dependencies are registered in `postProcessBeanFactory`. This allows a `ServletReqest` to be autowired into an early initialized bean and brings parity with WAR based deployments. Closes gh-14990
1 parent fb85d0a commit b60da5f

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactor
114114
beanFactory.addBeanPostProcessor(
115115
new WebApplicationContextServletContextAwareProcessor(this));
116116
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
117+
registerWebApplicationScopes(null);
117118
}
118119

119120
@Override
@@ -217,19 +218,22 @@ public void onStartup(ServletContext servletContext) throws ServletException {
217218

218219
private void selfInitialize(ServletContext servletContext) throws ServletException {
219220
prepareEmbeddedWebApplicationContext(servletContext);
220-
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
221-
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
222-
beanFactory);
223-
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
224-
getServletContext());
225-
existingScopes.restore();
226-
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
227-
getServletContext());
221+
registerWebApplicationScopes(servletContext);
222+
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),
223+
servletContext);
228224
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
229225
beans.onStartup(servletContext);
230226
}
231227
}
232228

229+
private void registerWebApplicationScopes(ServletContext servletContext) {
230+
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
231+
getBeanFactory());
232+
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory(),
233+
servletContext);
234+
existingScopes.restore();
235+
}
236+
233237
/**
234238
* Returns {@link ServletContextInitializer}s that should be used with the embedded
235239
* Servlet context. By default this method will first attempt to find

spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,15 @@
4141
import org.mockito.InOrder;
4242
import org.mockito.MockitoAnnotations;
4343

44+
import org.springframework.beans.BeansException;
4445
import org.springframework.beans.MutablePropertyValues;
4546
import org.springframework.beans.factory.BeanCreationException;
4647
import org.springframework.beans.factory.config.BeanDefinition;
48+
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
4749
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
4850
import org.springframework.beans.factory.config.ConstructorArgumentValues;
4951
import org.springframework.beans.factory.config.Scope;
52+
import org.springframework.beans.factory.support.AbstractBeanDefinition;
5053
import org.springframework.beans.factory.support.RootBeanDefinition;
5154
import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean;
5255
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -466,7 +469,8 @@ public void postProcessEmbeddedServletContainerFactory() throws Exception {
466469
}
467470

468471
@Test
469-
public void doesNotReplaceExistingScopes() throws Exception { // gh-2082
472+
public void doesNotReplaceExistingScopes() throws Exception {
473+
// gh-2082
470474
Scope scope = mock(Scope.class);
471475
ConfigurableListableBeanFactory factory = this.context.getBeanFactory();
472476
factory.registerScope(WebApplicationContext.SCOPE_REQUEST, scope);
@@ -482,6 +486,29 @@ public void doesNotReplaceExistingScopes() throws Exception { // gh-2082
482486
.isSameAs(scope);
483487
}
484488

489+
@Test
490+
public void servletRequestCanBeInjectedEarly() throws Exception {
491+
// gh-14990
492+
addEmbeddedServletContainerFactoryBean();
493+
RootBeanDefinition beanDefinition = new RootBeanDefinition(
494+
WithAutowiredServletRequest.class);
495+
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
496+
this.context.registerBeanDefinition("withAutowiredServletRequest",
497+
beanDefinition);
498+
this.context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
499+
500+
@Override
501+
public void postProcessBeanFactory(
502+
ConfigurableListableBeanFactory beanFactory) throws BeansException {
503+
WithAutowiredServletRequest bean = beanFactory
504+
.getBean(WithAutowiredServletRequest.class);
505+
assertThat(bean.getRequest()).isNotNull();
506+
}
507+
508+
});
509+
this.context.refresh();
510+
}
511+
485512
private void addEmbeddedServletContainerFactoryBean() {
486513
this.context.registerBeanDefinition("embeddedServletContainerFactory",
487514
new RootBeanDefinition(MockEmbeddedServletContainerFactory.class));
@@ -534,4 +561,18 @@ public void doFilter(ServletRequest request, ServletResponse response,
534561

535562
}
536563

564+
protected static class WithAutowiredServletRequest {
565+
566+
private final ServletRequest request;
567+
568+
public WithAutowiredServletRequest(ServletRequest request) {
569+
this.request = request;
570+
}
571+
572+
public ServletRequest getRequest() {
573+
return this.request;
574+
}
575+
576+
}
577+
537578
}

0 commit comments

Comments
 (0)