Spring父容器与Spring MVC子容器是如何体现出父子关系的

平常的子类继承父类通过extends关键字来实现,那么Spring父容器与Spring MVC子容器是如何体现出父子关系的呢?
容器指的是一个类吗?Spring容器是哪个类,Spring MVC容器又是哪个类?

阅读 5k
4 个回答

所谓容器,就是上下文,在这同一个上下文里,大家可以共享一些东西。

Spring应用启动时,会先读取web.xml文件,调用ContextLoaderListener创建Spring容器,也就是你说的父容器。

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

Listener创建完之后,开始创建Servlet:

    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

这时候这个DispatcherServlet开始试图创建SpringMVCApplicationContext,它先找刚才由上面那个ContextLoaderListener创建的SpringApplicationContext,找到后,把SpringApplicationContext作为参数传给DispatcherServletApplicationContextsetParent方法,这样SpringMVC的容器就变成了Spring容器的儿子。

因为在SpringMVC这个子容器创建的时候指定了它的Spring父容器,所以儿子能找到父亲,所以SpringMVC这个子容器里的Bean可以调用父容器的服务,而父容器不知道有这个儿子的存在(一个不负责任的父亲),父容器里的Bean不能调用子容器里的服务。

想必Servlet的关系就不必多说了,直接上代码吧
HttpServletBean 继承了 HttpServlet,init方法如下

    @Override
    public final void init() throws ServletException {
        // Let subclasses do whatever initialization they like.
        initServletBean();
    }

看看子类FrameworkServlet#initServletBean 方法

@Override
protected final void initServletBean() throws ServletException {
    this.webApplicationContext = initWebApplicationContext();
    initFrameworkServlet();
}

看看 initWebApplicationContext

protected WebApplicationContext initWebApplicationContext() {
        WebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        WebApplicationContext wac = null;

        if (this.webApplicationContext != null) {
            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 ,看到没有,如果有就设置rootApplicationContext,
                        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. 看到这里就不多说了,初始化beanFactory
            onRefresh(wac);
        }

        if (this.publishContext) {
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
        }

        return wac;
    }

结束,就是辣么简单

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏