spring内幕(十)web项目中的容器初始化前置流程




    open-joonwhee-service WAR
 
    
        contextConfigLocation
        
            classpath*:config/spring/appcontext-*.xml
        
    
 
    
        org.springframework.web.context.ContextLoaderListener
    


在web.xml的 标签里面,配置有ContextLoaderListener监听器。
该监听器继承自contextLoader
spring内幕(十)web项目中的容器初始化前置流程_第1张图片

在contextLoaderListener初始化之后,会先初始化contextLoader
在这个里面有一个很关键的属性
DEFAULT_STRATEGIES_PATHspring内幕(十)web项目中的容器初始化前置流程_第2张图片

该属性是指
org/springframework/spring-web/4.3.2.RELEASE/spring-web-4.3.2.RELEASE.jar!/org/springframework/web/context/ContextLoader.properties

这个文件
spring内幕(十)web项目中的容器初始化前置流程_第3张图片
该文件的内容为
spring内幕(十)web项目中的容器初始化前置流程_第4张图片

因此这里就决定了 使用XmlWebApplicationContext 这个容器。

在加载defaultStrategies属性之后

因为ContextLoaderListener还实现了ServletContextListener接口,该接口的contextInitialized方法会在tomcat启动的时候调用。

在里面调用 initWebApplicationContext方法
1…创建一个 WebApplicationContext方法


protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
    // 1.确定要创建的应用上下文的Class
    Class contextClass = determineContextClass(sc);
    // 2.校验contextClass是否为ConfigurableWebApplicationContext或其子类、子接口
    if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
        throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
                "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
    }
    // 3.实例化contextClass,并强转成ConfigurableWebApplicationContext返回
    return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
}

在 determineContextClass(sc);方法里面 其实是根据之前contextLoader里面的属性获取到的XmlWebApplicationContext容器


protected Class determineContextClass(ServletContext servletContext) {
    // 1.从servletContext中解析初始化参数contextClass(web.xml可以配置该参数)
    String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
    if (contextClassName != null) {
        try {
            // 2.contextClassName不为空,则使用工具类构建出contextClassName的实例
            return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
        } catch (ClassNotFoundException ex) {
            throw new ApplicationContextException(
                    "Failed to load custom context class [" + contextClassName + "]", ex);
        }
    } else {
        // 3.如果没有配置contextClass参数,则从defaultStrategies缓存中拿到默认的WerApplicationContext对应的ClassName,
        // 即:org.springframework.web.context.support.XmlWebApplicationContext
        contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
        try {
            // 4.使用工具类构建出contextClassName的实例
            return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
        } catch (ClassNotFoundException ex) {
            throw new ApplicationContextException(
                    "Failed to load default context class [" + contextClassName + "]", ex);
        }
    }
}

你可能感兴趣的:(spring源码学习专栏)