2017-02-16 27 views
9

ПРЕДПОСЫЛКИАссоциация между: SpringIocContainer | ApplicationContext | WebApplicationContext

После чтения из 123456 Ссылки я пришел к следующему conclusion-

Как Spring MVC разработан более standered servlets и облегчают такую ​​же функциональность servlet context и application context .в весной есть два типа контекста ApplicationContext и WebApplicationContext -

ApplicationContext Инициализация: ContextLoaderListener, для одного приложения. 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. context и container кажется синонимы к большинству из нас, я хочу дать example.Let сказать, что мы имеем два диспетчера сервлета один для 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 ,

    Я не уверен, но не должно быть 2 IocContainer в единственном SpringApplication.

  3. BeanFactory т.е. SpringIocContainer есть, где вся объектный боб жизни, что когда-либо объектов, которые мы ассоциаты с WebApplicationContext является части Spring контейнера, как это контейнер инициализируется WebApplicationContext? Я хочу хочу знать, как делает они оба связаны друг с другом?

    И всякий раз, когда мы делали ctx.getBean() - это возвращает объект с весны контейнер, как это происходит между контекстом и контейнером ?

Существует аналогичный answer что отрицает оба же, он говорит

Spring поставляется с несколькими реализациями контейнеров, оба определения нагрузки фасоли, проволочная фасоль вместе, и отказаться от бобов по запросу, но ApplicationContext предлагает гораздо больше.

Итак, моя точка в том, почему оба определения боковых бобов, проводные бобы вместе, это своего рода переделка?

Еще одна вещь, даже если веб-приложение весной приводом или нет, должен быть контекст, который standard servlet обеспечивает и использовать в НТТР ......

весна следует за этим или весной обрабатывает это в некоторые другие manner.And весной context означает только IOC container, из которых некоторая часть загружается DispacherServlet и часть загружается ContextLoaderListner и может облегчить гораздо больше таких, как I18N, access to static resource и т.д ..

+1

«WebApplicationContext» - это «ApplicationContext». И 'ContextLoaderLIstener', и' DispatcherServlet' загружают экземпляр 'WebApplicationContext' (который фактически является интерфейсом). Существует только «ApplicationContext», независимо от того, связан ли он с веб-сайтом или не веб-сайтом. «ApplicationContext» - это контейнер. –

+2

@ M.Deinum Как вы указали, существует один «контекст» для каждого приложения, есть много писем, которые объясняют существование обоих, некоторые из них упоминаются в самом вопросе. Более того, если вы инициализируете свой контекст «DispatcherServlet», то есть нет 'ContextLoaderListner' ans call spring security' 'this будет вызывать' IllegalStateException: No ApplicationContext found: ' –

+1

Нет, я нигде не указал на то, что существует один контекст ... Но только весна имеет понятие «ApplicationContext» .. Который может быть типа 'WebApplicationContext'. Может быть 1 или 100. То, что я намекнул на то, что «ContextLoaderListener» и «DispatcherServlet» загружают «WebApplicationContext». «ContextLoaderLIstener» загружает контекст, обычно называемый корневым контекстом, который также предоставляет доступ к фильтрам. Вы также можете это сделать (если у вас есть один 'DispatcherServlet', чтобы разоблачить его как корневой контекст (и это, как правило, то, что люди забывают, приводя к проблеме, на которую вы указываете)). –

ответ

0

в принципе, в пружине Приложение MVC весенние контексты регистрируются в e сервлет контекста веб-приложения. Вы можете сделать это в файле web.xml, установив весну ContextLoaderListener или с конфигурацией java. В комментариях я указал на эту ссылку, где он объясняет, как это делается с помощью классов конфигурации Java:

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

Там вы можете увидеть, как выполняется «соединение». Затем вы спросили в комментариях, что это достигается:

WebApplicationContextUtils.getWebApplicationContext(myServle‌​t.getServletContext(‌​)) 

Если вы проверить код этого класса, вы можете видеть, что получает WebApplicationContext из атрибутов ServletContext. Эти атрибуты задаются при инициализации веб-приложения. Если вы заметили, в ContextLoader класса (родителя ContextLoaderListener), в методе 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(‌​)):

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

Итак, как вы можете себе все ответы на ваши сомнения приводятся в коде, который выполняется весной во время запуска веб-приложения.

Надеюсь, я ответил на ваш вопрос.

0

для вашего Сомнения 1

В рессоры приложении есть один экземпляр контекста, который является WebAplicationCntext за DispatcherServlet.Что может быть см на супер интерфейс ApplicationContext -

public class SomeThing implements ApplicationContextAware{ 
@Override 
public void setApplicationContext(ApplicationContext ctx) throws BeanException{ 
//this context object is `WebApplicationContext` which is refer by `ApplicationContext`. 
} 
} 

Весной контексте означает только МОК контейнер, некоторые из которых часть нагруженный DispacherServlet и какая-то часть загружается ContextLoaderListner и может способствовать гораздо больше таких, как I18N, доступ к статическому ресурсу и т. Д.

Вышеуказанное понимание почти правильно. Весна Все объекты WebApplicationContext имеют общую общую ссылку, которая составляет rootContext.

Этот ответ не включает ответ doubt2, doubt3 и why all context perform same task.