之间的关联:SpringIocContainer | ApplicationContext |的WebApplicationContext

时间:2017-02-16 17:20:06

标签: java spring spring-mvc ioc-container

背景

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

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

ApplicationContextContextLoaderListener初始化,每个应用程序单个实例。 按WebApplicationContext加载DispatcherServlet

我们可以理解上面这个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

    我不确定,但单个SpringApplication中一定不能有2个IocContainer。

  3. BeanFactory即SpringIocContainer,所有bean对象所在的位置 生活,我们与WebApplicationContext联系的对象是什么 Spring容器的一部分,这个容器是如何初始化的 WebApplicationContext?我想知道他们俩是怎么回事 相互联系?

    每当我们做ctx.getBean()时 - 这会从spring返回对象 容器,如何在上下文和容器之间进行通信 会发生什么?

  4. 有一个类似的answer否认两者都相同,它说

      

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

    所以我的观点是为什么加载bean定义,连接bean,这是一种返工?

    即使网络应用程序是弹簧驱动还是没有,还有一个问题,必须有一个standard servlet在Http通信中提供和使用的上下文......

    Spring跟随此或spring以其他方式处理此问题。在spring context中表示只是IOC container,其中某些部分由DispacherServlet加载,而某些部分由ContextLoaderListner加载I18N可以提供更多便利,例如access to static resource.fix{ border: 1px solid blue; width: 20%; display:inline-block; float:left; } .rest{ float: right; border: 1px solid red; width:80%; } 等。

2 个答案:

答案 0 :(得分:0)

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

spring: where does `@autowired` look for beans?

在那里你可以看到'连接'是如何完成的。然后,您在评论中询问了这一点:

ContextLoaderListener

如果您检查该类的代码,则可以看到它从WebApplicationContextUtils.getWebApplicationContext(myServle‌​t.getServletContext(‌​)) 的属性中获取WebApplicationContext。这些属性在Web应用程序的初始化中设置。如果您注意到ServletContext类(ContextLoader的父级),在ContextLoaderListener方法中它将这些属性设置为servlet上下文:

initWebApplicationContext

这是在这一行完成的:

/**
     * 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(‌​))

因此,您可以看到所有疑问的答案都在Spring应用程序启动期间执行的代码中。

希望我回答你的问题。

答案 1 :(得分:0)

怀疑1

在spring应用程序中,有一个上下文实例,WebAplicationCntextDispatcherServlet。这可以通过超级接口引用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,访问静态资源等 < / p>

您的上述理解几乎是正确的。在Spring中,所有WebApplicationContext对象都共享一些公共引用rootContext

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