BackGround
在阅读了 1 2 3 4 5 6 链接后,我得出了以下结论——
由于Spring mvc设计了standered servlets
,并促进了servlet context
和application context
的相同功能。在春天,有两种类型的背景ApplicationContext
和WebApplicationContext
-
ApplicationContext
通过ContextLoaderListener
初始化,每个应用程序单个实例。WebApplicationContext
按DispatcherServlet
加载。
我们可以像这样理解上面ApplicationContext
扩展WebApplicationContext
所以与ApplicationContext
相关的内容最终都是WebApplicationContext
的一部分。
怀疑
-
ApplicationContextAware
提供哪个context
对象。public class SomeThing implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext ctx) throws BeanException { //this context object is `ApplicationContext` or `WebApplicationContext`? } }
-
context
和container
对我们大多数人来说似乎是同义词,我想 举个例子。假设我们有两个调度程序 servlet 一个用于rest
和其他mvc
.第一调度员-
public class RestInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/rest/*" }; } }
第二调度员-
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/mvc/*" }; } }
比这里有两个实例
WebApplicationContext
,那些 公共部件由ContextLoaderListner
加载,如 中定义rootContext
.我不确定,但是在单个Spring应用程序中一定不能有2个IocContainer。
-
BeanFactory 即 SpringIocContainer 是,其中所有 bean 对象 生活,无论我们与之相关的对象是什么
WebApplicationContext
Spring容器的一部分,这个容器是如何初始化的WebApplicationContext
?我想知道他们俩是怎么回事 彼此关联?每当我们做
ctx.getBean()
- 这会从春天返回对象 容器,上下文和容器之间的这种通信如何 发生?
有一个类似的答案否认两者是相同的,它说
Spring 带有几个容器实现,两者都加载 bean 定义,将 bean 连接在一起,并根据请求分配 bean,但 ApplicationContext 提供了更多。
所以我的观点是为什么两者都加载豆定义,将豆子串联在一起,这是一种返工?
还有一件事,即使Web应用程序是否是弹簧驱动的,也必须有一个standard servlet
提供并在Http通信中使用的上下文......
春天遵循这一点,或者春天以其他方式处理它。在春天,context
意味着一个公正的IOC container
,其中一部分由DispacherServlet
装载,一部分由ContextLoaderListner
装载,可以方便更多,例如I18N
,access to static resource
等。
For Your Doubt 1
在 spring 应用程序中,有一个上下文实例,每个DispatcherServlet
WebAplicationCntext
。可以通过超级接口ApplicationContext
来引用 -
public class SomeThing implements ApplicationContextAware{
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeanException{
//this context object is `WebApplicationContext` which is refer by `ApplicationContext`.
}
}
在春天,上下文意味着一个IOC容器,其中一部分由DispacherServlet加载,一些部分由ContextLoaderListner加载,可以促进更多,如I18N,访问静态资源等
。你的上述理解几乎是正确的。在 Spring 中,所有WebApplicationContext
对象共享一些公共引用,即rootContext
。
这个答案不包括doubt2
、doubt3
和why all context perform same task
的答案。
基本上,在 Spring MVC 应用程序中,Spring 上下文是在 Web 应用程序的 servlet 上下文中注册的。您可以在web.xml
文件中设置 SpringContextLoaderListener
或使用 java 配置来执行此操作。在评论中,我指出了这个链接,它解释了如何通过java配置类完成此操作:
春天:"@autowired"在哪里寻找豆子?
在那里,您可以看到"连接"是如何完成的。然后,您在评论中询问这实现了什么:
WebApplicationContextUtils.getWebApplicationContext(myServlet.getServletContext())
如果您检查该类的代码,您可以看到它从ServletContext
的属性中获取WebApplicationContext
。这些属性在 Web 应用程序的初始化中设置。如果您注意到,在ContextLoader
类(ContextLoaderListener
的父级)中,在initWebApplicationContext
方法中,它将这些属性设置为 servlet 上下文:
/**
* Initialize Spring's web application context for the given servlet context,
* using the application context provided at construction time, or creating a new one
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
* @param servletContext current servlet context
* @return the new WebApplicationContext
* @see #ContextLoader(WebApplicationContext)
* @see #CONTEXT_CLASS_PARAM
* @see #CONFIG_LOCATION_PARAM
*/
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
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.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!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) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}
return this.context;
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
catch (Error err) {
logger.error("Context initialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
throw err;
}
}
这是在这一行中完成的:
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
如您所见,它存储在您尝试使用WebApplicationContextUtils.getWebApplicationContext(myServlet.getServletContext())
获取它的同一位置:
/**
* Find the root {@code WebApplicationContext} for this web app, typically
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
* <p>Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app, or {@code null} if none
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
因此,如您所见,所有问题的答案都在 spring 在 Web 应用程序启动期间执行的代码中。
希望我回答了你的问题。