spring mvc 之ContextLoaderListener

来源:互联网 发布:apache 配置文件路径 编辑:程序博客网 时间:2024/06/05 03:32

springmvc 的源码分析要从web.xml开始。
2个重要的类一个是org.springframework.web.context.ContextLoaderListener,一个是org.springframework.web.servlet.DispatcherServlet

ContextLoaderListener的作用是启动web容器时,能够自动装配ApplicationContext的配置信息。
ContextLoaderListener实现了 ServletContextListener接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
初始化WebApplicationContext

@Override    public void contextInitialized(ServletContextEvent event) {        initWebApplicationContext(event.getServletContext());    }

WebApplicationContext 继承ApplicationContext,是在ApplicationContext的基础上增加一些web的操作及属性。和ClassPathXmlApplicationContext类提供的功能。

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            // 初始化context            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中,以   WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key    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;        }    }

创建webApplicationContext实例

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {        Class<?> contextClass = determineContextClass(sc);        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {            throw new ApplicationContextException("Custom context class [" + contextClass.getName() +                    "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");        }        return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);    }
protected Class<?> determineContextClass(ServletContext servletContext) {        String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);        if (contextClassName != null) {            try {                return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());            }            catch (ClassNotFoundException ex) {                throw new ApplicationContextException(                        "Failed to load custom context class [" + contextClassName + "]", ex);            }        }        else {            contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());            try {                return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());            }            catch (ClassNotFoundException ex) {                throw new ApplicationContextException(                        "Failed to load default context class [" + contextClassName + "]", ex);            }        }    }
static {        try {        //DEFAULT_STRATEGIES_PATH=ContextLoader.properties            ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);        }        catch (IOException ex) {            throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());        }    }

ContextLoader.properties

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

初始化的过程
1.读取ContextLoader.properties,提取实现WebApplicationContext接口的实现类XmlWebApplicationContext,并且哥哥那句这个实现累通过反射的方式进行实例的创建
2.将实例记录在servletContext中
3.映射当前的类加载器与创建的实例到全局变量currentContextPerThread中