美文网首页
2021-12-16 Spring中父子容器的创建

2021-12-16 Spring中父子容器的创建

作者: 归去来ming | 来源:发表于2021-12-16 11:09 被阅读0次

    1,父容器的创建

    // ContextLoaderListener
    @Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }
    /**
    ContextLoader的initWebApplicationContext方法
    这里为什么要判断instanceof ConfigurableWebApplicationContext ?
    因为默认创建的是XmlWebApplicationContext,平常写Demo经常用到的
    ClassPathXmlApplicationContext类和FileSystemXmlApplicationContext类
    不属于这个类的子类或实现类
    */
    if (this.context == null) {
        this.context = createWebApplicationContext(servletContext);
    }
    if (this.context instanceof ConfigurableWebApplicationContext) {
        ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
        if (!cwac.isActive()) {
            if (cwac.getParent() == null) {
                // loadParentContext方法默认返回的也是null
                ApplicationContext parent = this.loadParentContext(servletContext);
                cwac.setParent(parent);
            }
    
            this.configureAndRefreshWebApplicationContext(cwac, servletContext);
        }
    }
    
    从这张类图上可以清晰看到,只有XmlWebApplicationContext是ConfigurableWebApplicationContext的实现类,而ClassPathXmlApplicationContext和FileSystemXmlApplicationContext不是。 image.png

    实际上ConfigurableWebApplicationContext有多个子类或实现类:


    image.png

    2,子容器的创建

    // FrameworkServlet
    protected WebApplicationContext initWebApplicationContext() {
        // 父容器
        WebApplicationContext rootContext =
                WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        // 子容器
        WebApplicationContext wac = null;
          // FrameworkServlet构造函数创建了webApplicationContext,见AbstractDispatcherServletInitializer类
        if (this.webApplicationContext != null) {
            // A context instance was injected at construction time -> use it
            wac = this.webApplicationContext;
            if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                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 -> set
                        // the root application context (if any; may be null) as the parent
                        // 设置父子容器关系
                        cwac.setParent(rootContext);
                    }
                    configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }
        if (wac == null) {
            // No context instance was injected at construction time -> see if one
            // has been registered in the servlet context. If one exists, it is assumed
            // that the parent context (if any) has already been set and that the
            // user has performed any initialization such as setting the context id
            wac = findWebApplicationContext();
        }
        if (wac == null) {
            // No context instance is defined for this servlet -> create a local one
            wac = createWebApplicationContext(rootContext);
        }
    
        if (!this.refreshEventReceived) {
            // Either the context is not a ConfigurableApplicationContext with refresh
            // support or the context injected at construction time had already been
            // refreshed -> trigger initial onRefresh manually here.
            onRefresh(wac);
        }
    
        if (this.publishContext) {
            // Publish the context as a servlet context attribute.
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
                        "' as ServletContext attribute with name [" + attrName + "]");
            }
        }
    
        return wac;
    }
    
    图片.png
    // AbstractDispatcherServletInitializer
    protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
       return new DispatcherServlet(servletAppContext);
    }
    

    相关文章

      网友评论

          本文标题:2021-12-16 Spring中父子容器的创建

          本文链接:https://www.haomeiwen.com/subject/nttvfrtx.html