Spring WebApplicationContext

来源:互联网 发布:工程设计图软件 编辑:程序博客网 时间:2024/06/06 05:19
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {    String getId();    String getApplicationName();    String getDisplayName();    long getStartupDate();    ApplicationContext getParent();    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;}

ApplicationContext是spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了(IOC容器)。

public interface WebApplicationContext extends ApplicationContext {    String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";    String SCOPE_REQUEST = "request";    String SCOPE_SESSION = "session";    String SCOPE_GLOBAL_SESSION = "globalSession";    String SCOPE_APPLICATION = "application";    String SERVLET_CONTEXT_BEAN_NAME = "servletContext";    String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";    String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";    ServletContext getServletContext();}

在Web应用中,我们会用到WebApplicationContext,WebApplicationContext继承自ApplicationContext。
WebApplicationContext的初始化方式和BeanFactory、ApplicationContext有所区别,因为WebApplicationContext需要ServletContext实例,也就是说它必须拥有Web容器的前提下才能完成启动的工作。
有过Web开发经验的读者都知道可以在web.xml中配置Web容器监听器ServletContextListener,借助于该监听器我们就可以启动Spring Web应用上下文的工作。

spring为我们提供了用于启动WebApplicationContext的Web容器监听器:ContextLoaderListener,用来在web应用启动的时候来初始化WebApplicationContext

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {    public ContextLoaderListener() {    }    public ContextLoaderListener(WebApplicationContext context) {        super(context);    }    @Override    public void contextInitialized(ServletContextEvent event) {        initWebApplicationContext(event.getServletContext());    }    @Override    public void contextDestroyed(ServletContextEvent event) {        closeWebApplicationContext(event.getServletContext());        ContextCleanupListener.cleanupAttributes(event.getServletContext());    }}

当Servlet 容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由 ServletContextListener 来处理。
在 ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法。
- contextInitialized(ServletContextEvent sce) :当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化,并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。
- contextDestroyed(ServletContextEvent sce) :当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。

    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {        ...        this.context = createWebApplicationContext(servletContext);        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);        ...    }

我们发现,原来ContextLoader是把WebApplicationContext放在了ServletContext中,ServletContext也是一个“容器”,也是一个类似Map的结构,而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,我们如果要使用WebApplicationContext则需要从ServletContext取出,Spring提供了一个WebApplicationContextUtils类,可以方便的取出WebApplicationContext,只要把ServletContext传入就可以了。
WebApplicationContextUtils是一个抽象类,其提供了一个很便利的方法来获取spring应用的上下文即WebApplicationContext。

其中的静态方法getWebApplicationContext(ServletContext sc),提供一个ServletContext 类型参数即可。
其原理十分简单,在spring容器初始化的方法ContextLoader.initWebApplicationContext(ServletContext)中通过servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);已经将WebApplicationContext的实例放入ServletContext 中了。
然后在工具类的org.springframework.web.context.support.WebApplicationContextUtils的
getWebApplicationContext(ServletContext)方法中就可以通过传入的ServletContext参数获取到WebApplicationContext实例了。

public static WebApplicationContext getWebApplicationContext(ServletContext sc) {        return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);    }
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {        Assert.notNull(sc, "ServletContext must not be null");        Object attr = sc.getAttribute(attrName);        ...}

原创粉丝点击