2017-02-16 26 views
9

BackGroundSự liên kết giữa: SpringIocContainer | ApplicationContext | WebApplicationContext

Sau khi đọc từ 123456 Liên kết tôi đạt đến sau conclusion-

Như Xuân MVC được thiết kế trên standered servlets, và tạo điều kiện cùng một chức năng của servlet contextapplication context .Tại mùa xuân có hai loại ngữ cảnh ApplicationContextWebApplicationContext -

ApplicationContext khởi tạo bởi ContextLoaderListener, một lần cho mỗi ứng dụng. WebApplicationContext được tải bởi mỗi DispatcherServlet.

Chúng ta có thể hiểu ở trên như ApplicationContext này kéo dài bởi WebApplicationContext vì vậy những gì từng thứ gắn liền với ApplicationContext ở cuối này là một phần của WebApplicationContext.

nghi ngờ

  1. ApplicationContextAware Mời mà context đối tượng.

    public class SomeThing implements ApplicationContextAware{ 
    @Override 
    public void setApplicationContext(ApplicationContext ctx) throws BeanException{ 
    //this context object is `ApplicationContext` or `WebApplicationContext`? 
    } 
    } 
    
  2. contextcontainer dường như đồng nghĩa với hầu hết chúng ta, tôi muốn đưa ra một example.Let nói rằng chúng ta có hai servlet phối một cho rest và khác cho mvc.

    Đầu tiên Dispatcher -

    public class RestInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
        @Override 
        protected String[] getServletMappings() { 
         return new String[] { "/rest/*" }; 
        } 
    } 
    

    Second Dispatcher -

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
         @Override 
         protected String[] getServletMappings() { 
          return new String[] { "/mvc/*" }; 
         } 
        } 
    

    hơn ở đây có hai thể hiện của WebApplicationContext, những phần chung được nạp bởi ContextLoaderListner như định nghĩa trong rootContext .

    Tôi không chắc chắn, nhưng không được có 2 IocContainer trong một SpringApplication đơn lẻ.

  3. BeanFactory tức SpringIocContainer là, nơi tất cả các đối tượng đậu cuộc sống, những gì từng đối tượng chúng tôi cộng với WebApplicationContext là phần của container mùa xuân, như thế nào chứa này được khởi tạo bởi WebApplicationContext? Tôi muốn muốn biết làm thế nào họ cả hai có liên quan với nhau không?

    Và bất cứ khi nào chúng tôi đã làm ctx.getBean() - điều này trả về đối tượng từ mùa xuân container, làm thế nào giao tiếp này giữa bối cảnh và container sẽ xảy ra?

Có một tương tự answer mà phủ nhận cả hai đều giống nhau, nó nói

mùa xuân đi kèm với một số triển khai container, Cả hai định nghĩa bean tải, dây đậu với nhau, và phân phát các bean theo yêu cầu, nhưng một ApplicationContext cung cấp nhiều hơn nữa.

Vì vậy, quan điểm của tôi là lý do cả hai định nghĩa hạt tải, hạt dây với nhau, đây là loại làm lại?

Một điều nữa mặc dù ứng dụng web được mùa xuân hướng hay không, thì phải có một bối cảnh mà standard servlet cung cấp và sử dụng trong giao tiếp Http ......

mùa xuân sau này hoặc mùa xuân xử lý này trong một số manner.And khác vào mùa xuân context có nghĩa là một chỉ IOC container, trong đó một số phần được tải bởi DispacherServlet và một số phần được tải bởi ContextLoaderListner và có thể tạo điều kiện nhiều hơn nữa như I18N, access to static resource vv ..

+1

Một 'WebApplicationContext' là một' ApplicationContext'. Cả hai 'ContextLoaderLIstener' và' DispatcherServlet' nạp một cá thể của 'WebApplicationContext' (thực ra là một giao diện). Chỉ có một 'ApplicationContext' bất chấp thực tế nếu nó là web hoặc không liên quan đến web. 'ApplicationContext' LÀ vùng chứa. –

+2

@ M.Deinum Khi bạn chỉ có một 'ngữ cảnh' cho mỗi ứng dụng, có rất nhiều whitepapers đã giải thích sự tồn tại của cả hai, một số trong số chúng được đề cập trong câu hỏi chính nó.Ngay cả nếu bạn khởi tạo ngữ cảnh của mình bằng' DispatcherServlet' chỉ có nghĩa là không 'ContextLoaderListner' ans gọi bảo mật mùa xuân' 'điều này sẽ ném' IllegalStateException: Không có ApplicationContext tìm thấy: ' –

+1

Không có nơi nào tôi chỉ ra rằng có một ngữ cảnh duy nhất ... có khái niệm 'ApplicationContext' .. Nó có thể thuộc kiểu' WebApplicationContext'. Có thể có 1 hoặc 100. Những gì tôi ám chỉ rằng cả hai 'ContextLoaderListener' và' DispatcherServlet' tải một 'WebApplicationContext'. 'ContextLoaderLIstener' tải một ngữ cảnh thường được gọi là ngữ cảnh gốc, đó cũng là những gì các bộ lọc có thể truy cập. Bạn cũng có thể làm cho nó (nếu bạn có một 'DispatcherServlet' để lộ ra cái đó làm ngữ cảnh gốc (và đó thường là những gì mọi người quên dẫn đến vấn đề bạn trỏ vào)). –

Trả lời

0

về cơ bản, trong một mùa xuân Ứng dụng MVC ngữ cảnh mùa xuân được đăng ký trong lần thứ e servlet context của ứng dụng web. Bạn có thể làm điều đó trong cài đặt tệp web.xml vào mùa xuân ContextLoaderListener hoặc với cấu hình java. Trong những ý kiến ​​tôi chỉ ra liên kết này, nơi nó giải thích cách này được thực hiện thông qua các lớp cấu hình java:

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

Ở đó bạn có thể thấy cách 'kết nối' được thực hiện. Sau đó, bạn hỏi trong các ý kiến ​​điều này đạt được:

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

Nếu bạn kiểm tra mã của lớp đó bạn có thể thấy nó được WebApplicationContext từ các thuộc tính của ServletContext. Các thuộc tính này được đặt trong khởi tạo ứng dụng web. Nếu bạn nhận thấy, trong lớp ContextLoader (mẹ của ContextLoaderListener), trong phương pháp initWebApplicationContext nó đặt những thuộc tính này với bối cảnh 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; 
     } 
    } 

đó được thực hiện ở dòng này:

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 

Như bạn có thể thấy, nó được lưu trữ trong cùng một vị trí nơi bạn đang cố gắng để có được nó với 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); 
    } 

Vì vậy, khi bạn có thể xem tất cả câu trả lời cho những nghi ngờ của bạn là trong mã mà mùa xuân thực hiện trong khi khởi động ứng dụng web.

Hy vọng tôi đã trả lời câu hỏi của bạn.

0

Đối với Doubt của bạn 1

Trong một ứng dụng mùa xuân có một trường hợp duy nhất của bối cảnh Đó là WebAplicationCntext mỗi DispatcherServlet.Mà có thể được tham khảo bởi một giao diện siêu ApplicationContext -

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

Vào mùa xuân, bối cảnh là một chỉ IOC container, trong đó một số phần được tải bởi DispacherServlet và một số phần được tải bởi ContextLoaderListner và có thể tạo điều kiện nhiều hơn nữa như I18N, quyền truy cập vào tài nguyên tĩnh, v.v.

Sự hiểu biết ở trên của bạn gần như chính xác.Trong mùa xuân Tất cả các đối tượng chung là rootContext.

Câu trả lời này không bao gồm câu trả lời của doubt2, doubt3why all context perform same task.

Các vấn đề liên quan