2017-01-09 7 views
0

私はルートコンテキストは、MVCコンテキストは、コントローラ が含まれているモデル、リポジトリなど spring: `@ autowired`はどこで豆を探しますか?

  • を含む2つのコンテキスト(私のAbstractAnnotationConfigDispatcherServletInitializerサブクラスで宣言されているように)

    • とSpring MVCのアプリケーションを持っています

      今、リポジトリをコントローラに注入できますが、なぜですか?

      • ウェブコンテキストには、ルートコンテキストの豆も含まれていますか(@Importなど)。ドキュメンテーションは親子関係を持っていることを暗示していますが、Webコンテキストを調べることで、内部にリポジトリBeanはありません。
      • @Autowiredは複数のコンテキストで機能しますか?そしてもしそうなら、どのように?私は通常、このクラスは、あなたが明示的に親子コンテキスト、すべてのあなたの豆、コンポーネントを作成する場合を除きなど@Configurationsと@Components

        を見つけComponentScanおよび/またはインポートを持ってAbstractAnnotationConfigDispatcherServletInitializer.getRootConfigClasses()から単一のコンテキストを返し

  • +0

    web.xmlファイルを投稿できますか? – mlg

    +0

    私はweb.xmlを持たず、初期化はサブクラス –

    答えて

    1

    両方のコンテキストは、同じサーブレットコンテキストに格納されます。

    あなたが気付いた場合、AbstractDispatcherServletInitializerAbstractAnnotationConfigDispatcherServletInitializerの親クラスは、最初にによって作成され、それは最初rootApplicationContextを追加し、その親onStartupメソッドを呼び出し、それを行うにはonStartup方法

    @Override 
        public void onStartup(ServletContext servletContext) throws ServletException { 
         super.onStartup(servletContext); 
         registerDispatcherServlet(servletContext); 
        } 
    

    に登録を行います最後にcreateRootApplicationContextAbstractAnnotationConfigDispatcherServletInitializerクラスのメソッドとはのServletContextに追加onStartup法に受信:

    @Override 
        public void onStartup(ServletContext servletContext) throws ServletException { 
         registerContextLoaderListener(servletContext); 
        } 
    
        /** 
        * Register a {@link ContextLoaderListener} against the given servlet context. The 
        * {@code ContextLoaderListener} is initialized with the application context returned 
        * from the {@link #createRootApplicationContext()} template method. 
        * @param servletContext the servlet context to register the listener against 
        */ 
        protected void registerContextLoaderListener(ServletContext servletContext) { 
         WebApplicationContext rootAppContext = createRootApplicationContext(); 
         if (rootAppContext != null) { 
          ContextLoaderListener listener = new ContextLoaderListener(rootAppContext); 
          listener.setContextInitializers(getRootApplicationContextInitializers()); 
          servletContext.addListener(listener); 
         } 
         else { 
          logger.debug("No ContextLoaderListener registered, as " + 
            "createRootApplicationContext() did not return an application context"); 
         } 
        } 
    

    そして、

    /** 
        * Register a {@link DispatcherServlet} against the given servlet context. 
        * <p>This method will create a {@code DispatcherServlet} with the name returned by 
        * {@link #getServletName()}, initializing it with the application context returned 
        * from {@link #createServletApplicationContext()}, and mapping it to the patterns 
        * returned from {@link #getServletMappings()}. 
        * <p>Further customization can be achieved by overriding {@link 
        * #customizeRegistration(ServletRegistration.Dynamic)} or 
        * {@link #createDispatcherServlet(WebApplicationContext)}. 
        * @param servletContext the context to register the servlet against 
        */ 
        protected void registerDispatcherServlet(ServletContext servletContext) { 
         String servletName = getServletName(); 
         Assert.hasLength(servletName, "getServletName() must not return empty or null"); 
    
         WebApplicationContext servletAppContext = createServletApplicationContext(); 
         Assert.notNull(servletAppContext, 
           "createServletApplicationContext() did not return an application " + 
           "context for servlet [" + servletName + "]"); 
    
         FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext); 
         dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers()); 
    
         ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet); 
         Assert.notNull(registration, 
           "Failed to register servlet with name '" + servletName + "'." + 
           "Check if there is another servlet registered under the same name."); 
    
         registration.setLoadOnStartup(1); 
         registration.addMapping(getServletMappings()); 
         registration.setAsyncSupported(isAsyncSupported()); 
    
         Filter[] filters = getServletFilters(); 
         if (!ObjectUtils.isEmpty(filters)) { 
          for (Filter filter : filters) { 
           registerServletFilter(servletContext, filter); 
          } 
         } 
    
         customizeRegistration(registration); 
        } 
    

    あなたがリポジトリを注入することができ理由です:その後、AbstractDispatcherServletInitializerは、それがAbstractAnnotationConfigDispatcherServletInitializerクラスである抽象メソッドcreateServletApplicationContextを呼び出した後、同じのServletContextに追加されdispatcherServletを作成し、そのregisterDispatcherServletメソッドを呼び出します2つのコンテキストが同じServletContext内にあるためです。

    0

    サービスは単一のApplicationContextで終了します。明示的には、refresh()が呼び出される前にApplicationContextでsetParent()を呼び出しておく必要があることを意味します。

    これは、あなたが同じアプリケーションコンテキストから他のSpring Beanに@AutoWireできることを意味します(あなたがコンテキストを入れ子にしている場合autowired Beanは親コンテキストからのものであってもよい)

    編集 あなたがAbstractAnnotationConfigDispatcherServletInitializer.getServletConfigClasses()を使用した場合と、あなたのイニシャライザから2つのコンテキストを返すと、servletConfigコンテキストは子になり、ルートコンテキストは親になります。つまり、RootConfigコンテキストからservletConfigコンテキストBeanにBeanを自動配線できますが、それ以外の方法でBeanを自動配線することはできません。 - これは、通常、文脈をgetRootConfigClasses()nullからgetServletConfigClasses()に戻す理由です。

    +0

    を介して行われます。通常、同じクラスもディスパッチャサーブレットコンテキストを定義しています。ドキュメントには、通常、spring mvcに2つのコンテキストがあります。 '.setParent'はこれらの2つの豆のために内部的に呼び出されている可能性があります –

    +0

    個人的に私はライフサイクルが異なり、親が子なしで暮らすことができる場合のみ親子コンテキストを使用します - これはウェブアプリケーションでは当てはまりませんgetRootConfigClasses()からクラスを返します。 –

    関連する問題