鍍金池/ 問(wèn)答/Java/ Spring源碼分析:web環(huán)境中spring ioc容器的創(chuàng)建問(wèn)題

Spring源碼分析:web環(huán)境中spring ioc容器的創(chuàng)建問(wèn)題

ContextLoader 類中的方法

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

問(wèn)題:

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

這段代碼中第一個(gè) if 是創(chuàng)建 spring ioc 容器(webApplicationContext),第二個(gè) if 是什么含義?他有什么作用,針對(duì)哪種情況? ApplicationContext parent = loadParentContext(servletContext); 這樣代碼也不理解,主要是什么情況下才會(huì)發(fā)生

補(bǔ)充問(wèn)題:

clipboard.png

這個(gè)圖片中 SpringApplicationContext 有兩個(gè)子類 WebApplicationContextConfragubleApplicationContext,兩者的的定位是什么,有什么區(qū)別

回答
編輯回答
愛(ài)礙唉

翻閱相關(guān) Javadoc 可以得知:

Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
An ApplicationContext provides:

Bean factory methods for accessing application components. Inherited from ListableBeanFactory.

  • The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface.
  • The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface.
  • The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface.
  • Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a single parent context can be used by an entire web application, while each servlet has its own child context that is independent of that of any other servlet.

In addition to standard BeanFactory lifecycle capabilities, ApplicationContext implementations detect and invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.
-- ApplicationContext (Spring Framework 5.0.8.RELEASE API)

其中第四點(diǎn)提到 parent context 這個(gè)概念,即 Spring 容器支持多個(gè)上下文,以當(dāng)前上下文為最優(yōu)先配置,未配置的則通過(guò)父上下文來(lái)配置。

其他問(wèn)題請(qǐng)自行翻閱文檔:

2017年10月8日 15:42