之间的关联 : SpringIocContainer |应用程序上下文 |WebApplicationContext.



BackGround

在阅读了 1 2 3 4 5 6 链接后,我得出了以下结论——

由于Spring mvc设计了standered servlets,并促进了servlet contextapplication context的相同功能。在春天,有两种类型的背景ApplicationContextWebApplicationContext-

ApplicationContext通过ContextLoaderListener初始化,每个应用程序单个实例。WebApplicationContextDispatcherServlet加载。

我们可以像这样理解上面ApplicationContext扩展WebApplicationContext所以与ApplicationContext相关的内容最终都是WebApplicationContext的一部分。

怀疑

  1. ApplicationContextAware提供哪个context对象。

    public class SomeThing implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeanException {
    //this context object is `ApplicationContext` or `WebApplicationContext`?
    }
    }
    
  2. contextcontainer对我们大多数人来说似乎是同义词,我想 举个例子。假设我们有两个调度程序 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。

  3. BeanFactory 即 SpringIocContainer 是,其中所有 bean 对象 生活,无论我们与之相关的对象是什么WebApplicationContextSpring容器的一部分,这个容器是如何初始化的WebApplicationContext?我想知道他们俩是怎么回事 彼此关联?

    每当我们做ctx.getBean()- 这会从春天返回对象 容器,上下文和容器之间的这种通信如何 发生?

有一个类似的答案否认两者是相同的,它说

Spring 带有几个容器实现,两者都加载 bean 定义,将 bean 连接在一起,并根据请求分配 bean,但 ApplicationContext 提供了更多。

所以我的观点是为什么两者都加载豆定义,将豆子串联在一起,这是一种返工?

还有一件事,即使Web应用程序是否是弹簧驱动的,也必须有一个standard servlet提供并在Http通信中使用的上下文......

春天遵循这一点,或者春天以其他方式处理它。在春天,context意味着一个公正的IOC container,其中一部分由DispacherServlet装载,一部分由ContextLoaderListner装载,可以方便更多,例如I18Naccess to static resource等。

For Your Doubt 1

在 spring 应用程序中,有一个上下文实例,每个DispatcherServletWebAplicationCntext。可以通过超级接口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

这个答案不包括doubt2doubt3why all context perform same task的答案。

基本上,在 Spring MVC 应用程序中,Spring 上下文是在 Web 应用程序的 servlet 上下文中注册的。您可以在web.xml文件中设置 SpringContextLoaderListener或使用 java 配置来执行此操作。在评论中,我指出了这个链接,它解释了如何通过java配置类完成此操作:

春天:"@autowired"在哪里寻找豆子?

在那里,您可以看到"连接"是如何完成的。然后,您在评论中询问这实现了什么:

WebApplicationContextUtils.getWebApplicationContext(myServle‌​t.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(myServle‌​t.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 应用程序启动期间执行的代码中。

希望我回答了你的问题。

最新更新