2017-02-16 43 views
9

背景Associatation:SpringIocContainer | ApplicationContext | WebApplicationContext的

123456鏈接閱讀後,我得出了以下結論 -

由於Spring MVC設計了standered servlets,促進servlet contextapplication context。在春天的相同的功能有兩種類型的內容ApplicationContextWebApplicationContext -

ApplicationContext初始化爲ContextLoaderListener,單個instanse每個應用程序。 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似乎同義詞對我們大多數人,我想 給出example.Let說,我們有兩個調度的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. Bean工廠即SpringIocContainer是,所有的bean對象 生活,什麼都反對我們的同事與WebApplicationContext是Spring容器 一部分,請問這個容器由 WebApplicationContext初始化?我很想很想知道如何做他們都 相互關聯?

    而且每當我們做了ctx.getBean() - 這將返回來自彈簧 容器的對象,上下文和容器 之間的通信如何發生?

有一個類似answer否認的都是一樣的,它說

Spring提供了幾種容器的實現,這兩種負載bean定義,線豆在一起,並分配豆類根據要求,但一個ApplicationContext提供了更多。

所以我的觀點是爲什麼兩個加載bean定義,wire beans在一起,這是一種返工?

即使web應用程序是彈簧驅動與否,必須有其standard servlet提供和HTTP通訊使用的上下文......

春遵循此或彈簧處理這一件事情在彈簧context一些其他manner.And指剛剛IOC container,其中一些部分被DispacherServlet加載和一些部分由ContextLoaderListner加載並且可以促進更諸如I18Naccess to static resource等。

+1

'WebApplicationContext'是一個'ApplicationContext'。 「ContextLoaderLIstener」和「DispatcherServlet」都加載了一個「WebApplicationContext」實例(實際上是一個接口)。只有一個「ApplicationContext」,無論它是Web還是非Web相關的。 'ApplicationContext'是容器。 –

+2

@ M.Deinum正如你指出的那樣,每個應用程序都有一個'context',有很多白皮書解釋了兩者的存在,其中一些問題本身就提到了。而且,如果你僅僅通過'DispatcherServlet'初始化你的上下文, 'ContextLoaderListner'回覆spring security''這會拋出'IllegalStateException:沒有找到ApplicationContext:' – 2017-02-17 09:05:22

+1

不,我沒有指出只有一個上下文......但只有spring具有'ApplicationContext'的概念。它可以是'WebApplicationContext'類型。可以有1或100.我暗示'ContextLoaderListener'和'DispatcherServlet'都加載了一個'WebApplicationContext'。 ContextLoaderLIstener加載一個通常稱爲根上下文的上下文,這也是過濾器可以訪問的內容。你也可以這樣做(如果你有一個'DispatcherServlet'來公開那個作爲根環境(這通常是人們忘記導致你指向的問題))。 –

回答

0

基本上,在彈簧MVC應用程序spring的上下文在th。中註冊Web應用程序的servlet上下文。您可以在web.xml文件中設置彈簧ContextLoaderListener或使用java配置來執行此操作。在評論我指出這個鏈接,它說明了這是如何通過Java配置類進行:

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

在那裏,你可以看到「連接」是怎麼做的。然後,你在評論中問道,這是什麼實現:

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); 
    } 

所以你可以看到所有的在Web應用程序啓動過程中,Spring會執行的代碼將解答您的疑問。

希望我回答了你的問題。

0

對於你的懷疑1

在一個彈簧的應用有上下文的單個實例哪個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,訪問靜態資源等

你上面的理解幾乎是正確的。在春天所有的WebApplicationContext對象共享一些共同的參考,這是rootContext

本答案不包括答案doubt2,doubt3why all context perform same task

相關問題