Initialize application context with initializer-given ServletContext
Closes gh-22319
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractContextLoaderInitializer implements WebApplication
|
||||
protected void registerContextLoaderListener(ServletContext servletContext) {
|
||||
WebApplicationContext rootAppContext = createRootApplicationContext();
|
||||
if (rootAppContext != null) {
|
||||
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
|
||||
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext, servletContext);
|
||||
listener.setContextInitializers(getRootApplicationContextInitializers());
|
||||
servletContext.addListener(listener);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -152,7 +152,7 @@ public class ContextLoader {
|
||||
* The root WebApplicationContext instance that this loader manages.
|
||||
*/
|
||||
@Nullable
|
||||
private WebApplicationContext context;
|
||||
private WebApplicationContext rootContext;
|
||||
|
||||
/** Actual ApplicationContextInitializer instances to apply to the context. */
|
||||
private final List<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
|
||||
@@ -205,12 +205,12 @@ public class ContextLoader {
|
||||
* WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} and subclasses are
|
||||
* free to call the {@link #closeWebApplicationContext} method on container shutdown
|
||||
* to close the application context.
|
||||
* @param context the application context to manage
|
||||
* @param rootContext the application context to manage
|
||||
* @see #initWebApplicationContext(ServletContext)
|
||||
* @see #closeWebApplicationContext(ServletContext)
|
||||
*/
|
||||
public ContextLoader(WebApplicationContext context) {
|
||||
this.context = context;
|
||||
public ContextLoader(WebApplicationContext rootContext) {
|
||||
this.rootContext = rootContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,10 +259,10 @@ public class ContextLoader {
|
||||
try {
|
||||
// Store context in local instance variable, to guarantee that
|
||||
// it is available on ServletContext shutdown.
|
||||
if (this.context == null) {
|
||||
this.context = createWebApplicationContext(servletContext);
|
||||
if (this.rootContext == null) {
|
||||
this.rootContext = createWebApplicationContext(servletContext);
|
||||
}
|
||||
if (this.context instanceof ConfigurableWebApplicationContext cwac && !cwac.isActive()) {
|
||||
if (this.rootContext instanceof ConfigurableWebApplicationContext cwac && !cwac.isActive()) {
|
||||
// The context has not yet been refreshed -> provide services such as
|
||||
// setting the parent context, setting the application context id, etc
|
||||
if (cwac.getParent() == null) {
|
||||
@@ -273,14 +273,14 @@ public class ContextLoader {
|
||||
}
|
||||
configureAndRefreshWebApplicationContext(cwac, servletContext);
|
||||
}
|
||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
|
||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.rootContext);
|
||||
|
||||
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||
if (ccl == ContextLoader.class.getClassLoader()) {
|
||||
currentContext = this.context;
|
||||
currentContext = this.rootContext;
|
||||
}
|
||||
else if (ccl != null) {
|
||||
currentContextPerThread.put(ccl, this.context);
|
||||
currentContextPerThread.put(ccl, this.rootContext);
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
@@ -288,7 +288,7 @@ public class ContextLoader {
|
||||
logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
|
||||
}
|
||||
|
||||
return this.context;
|
||||
return this.rootContext;
|
||||
}
|
||||
catch (RuntimeException | Error ex) {
|
||||
logger.error("Context initialization failed", ex);
|
||||
@@ -506,7 +506,7 @@ public class ContextLoader {
|
||||
public void closeWebApplicationContext(ServletContext servletContext) {
|
||||
servletContext.log("Closing Spring root WebApplicationContext");
|
||||
try {
|
||||
if (this.context instanceof ConfigurableWebApplicationContext cwac) {
|
||||
if (this.rootContext instanceof ConfigurableWebApplicationContext cwac) {
|
||||
cwac.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.springframework.web.context;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletContextEvent;
|
||||
import jakarta.servlet.ServletContextListener;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
|
||||
* Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
|
||||
@@ -36,6 +39,10 @@ import jakarta.servlet.ServletContextListener;
|
||||
*/
|
||||
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
|
||||
|
||||
@Nullable
|
||||
private ServletContext servletContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code ContextLoaderListener} that will create a web application
|
||||
* context based on the "contextClass" and "contextConfigLocation" servlet
|
||||
@@ -56,6 +63,19 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||
public ContextLoaderListener() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ContextLoaderListener} with the given application context,
|
||||
* initializing it with the {@link ServletContextEvent}-provided
|
||||
* {@link ServletContext} reference which is spec-restricted in terms of capabilities.
|
||||
* <p>It is generally preferable to initialize the application context with a
|
||||
* {@link org.springframework.web.WebApplicationInitializer#onStartup}-given reference
|
||||
* which is usually fully capable.
|
||||
* @see #ContextLoaderListener(WebApplicationContext, ServletContext)
|
||||
*/
|
||||
public ContextLoaderListener(WebApplicationContext rootContext) {
|
||||
super(rootContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ContextLoaderListener} with the given application context. This
|
||||
* constructor is useful in Servlet initializers where instance-based registration of
|
||||
@@ -85,12 +105,15 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||
* WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} and the Spring
|
||||
* application context will be closed when the {@link #contextDestroyed} lifecycle
|
||||
* method is invoked on this listener.
|
||||
* @param context the application context to manage
|
||||
* @param rootContext the application context to manage
|
||||
* @param servletContext the ServletContext to initialize with
|
||||
* @since 6.2
|
||||
* @see #contextInitialized(ServletContextEvent)
|
||||
* @see #contextDestroyed(ServletContextEvent)
|
||||
*/
|
||||
public ContextLoaderListener(WebApplicationContext context) {
|
||||
super(context);
|
||||
public ContextLoaderListener(WebApplicationContext rootContext, ServletContext servletContext) {
|
||||
super(rootContext);
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +122,8 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent event) {
|
||||
initWebApplicationContext(event.getServletContext());
|
||||
ServletContext scToUse = getServletContextToUse(event);
|
||||
initWebApplicationContext(scToUse);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,8 +132,17 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
closeWebApplicationContext(event.getServletContext());
|
||||
ContextCleanupListener.cleanupAttributes(event.getServletContext());
|
||||
ServletContext scToUse = getServletContextToUse(event);
|
||||
closeWebApplicationContext(scToUse);
|
||||
ContextCleanupListener.cleanupAttributes(scToUse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preferably use a fully-capable local ServletContext instead of
|
||||
* the spec-restricted ServletContextEvent-provided reference.
|
||||
*/
|
||||
private ServletContext getServletContextToUse(ServletContextEvent event) {
|
||||
return (this.servletContext != null ? this.servletContext : event.getServletContext());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user