初探spring applicationContext在web容器中加载过程 首先从WEB.XML入手 ==>web.xml(1)

来源:互联网 发布:激战2捏脸数据库 编辑:程序博客网 时间:2024/06/08 16:49

2006-12-24 10:33

初探spring applicationContext在web容器中加载过程 首先从WEB.XML入手 ==>web.xml(1)



<context-param><param-name>webAppRootKey</param-name><param-value>task.root</param-value></context-param><!-- 定义SPRING配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/taskContext*.xml</param-value></context-param><context-param><param-name>log4jConfigLocation</param-name><param-value>/WEB-INF/log4j.properties</param-value></context-param><!-- 定义LOG4J监听器 --><listener><listener-class>org.springframework.web.util.Log4jConfigListener</listener-class></listener> <!-- 定义SPRING监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>进入contextLoaderListener看看到底加载时做了甚么 ==>org.springframework.web.context.ContextLoaderListener public class ContextLoaderListener implements ServletContextListener { private ContextLoader contextLoader; /*** Initialize the root web application context.*///当WEB上下文初始化时,系统会调用此方法public void contextInitialized(ServletContextEvent event) {this.contextLoader = createContextLoader(); //监听到WEB上下文初始化的时候执行SPRING上下文contextLoader的初始化工作this.contextLoader.initWebApplicationContext(event.getServletContext());} /*** Create the ContextLoader to use. Can be overridden in subclasses.* @return the new ContextLoader*/protected ContextLoader createContextLoader() {return new ContextLoader();} /*** Return the ContextLoader used by this listener.*/public ContextLoader getContextLoader() {return contextLoader;} /*** Close the root web application context.*/public void contextDestroyed(ServletContextEvent event) {if (this.contextLoader != null) {this.contextLoader.closeWebApplicationContext(event.getServletContext());}} } 看一下是怎么来初始化webapplicationContext的 ==>contextLoader.initWebApplicationContext public WebApplicationContext initWebApplicationContext(ServletContext servletContext)throws IllegalStateException, BeansException { 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!");} long startTime = System.currentTimeMillis();if (logger.isInfoEnabled()) {logger.info("Root WebApplicationContext: initialization started");}servletContext.log("Loading Spring root WebApplicationContext"); try {// Determine parent for root web application context, if any.ApplicationContext parent = loadParentContext(servletContext); // Store context in local instance variable, to guarantee that// it is available on ServletContext shutdown. //创建web上下文this.context = createWebApplicationContext(servletContext, parent);servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); if (logger.isInfoEnabled()) {logger.info("Using context class [" + this.context.getClass().getName() +"] for root WebApplicationContext");}if (logger.isDebugEnabled()) {logger.debug("Published root WebApplicationContext [" + this.context +"] 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;}} ==>contextLoader.createWebApplicationContext(servletContext, parent); protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent) throws BeansException {//根据servletContext来决定要实例化的WebApplicationContextClass contextClass = determineContextClass(servletContext);if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Custom context class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setParent(parent);wac.setServletContext(servletContext); //得到WEB.XML中设置的SPRING配置文件位置String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocation != null) {//把配置文件分段后设置到WebApplicationContext的ConfigLocations中wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));}//刷新WebApplicationContextwac.refresh();return wac;} ==>contextLoader.determineContextClass(servletContext); protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {//获得需要实例化的CONTEXT类名,在web.xml中有设置,如果没有设置,那么为空String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);if (contextClassName != null) {try {return ClassUtils.forName(contextClassName);}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);}}//如果在spring web.xml中没有设置context类位置,那么取得默认contextelse {//取得defaultStrategies配置文件中的WebApplicationContext属性contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());try {return ClassUtils.forName(contextClassName);}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);}}} SPRING上下文默认的策略是甚么呢? ==>contextLoader.defaultStrategies private static final Properties defaultStrategies; static {// Load default strategy implementations from properties file.// This is currently strictly internal and not meant to be customized// by application developers.try {//设置classpath为contextLoader同级目录ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);//加载该目录下的所有properties文件defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);}catch (IOException ex) {throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());}} 找到同级目录下的配置文件 ==>ContextLoader.properties # Default WebApplicationContext implementation class for ContextLoader.# Used as fallback when no explicit context implementation has been specified as context-param.# Not meant to be customized by application developers. #默认的WebApplicationContext为org.springframework.web.context.support.XmlWebApplicationContextorg.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext==>org.springframework.web.context.support.XmlWebApplicationContext public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** Default config location for the root context */ //配置了默认的spring配置文件public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; //配置文件默认BUILD路径public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; //配置文件默认后缀名public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; /*** Loads the bean definitions via an XmlBeanDefinitionReader.* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader* @see #initBeanDefinitionReader* @see #loadBeanDefinitions*///获得bean配置protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {//从BEAN工厂获得一个XmlBeanDefinitionReader 来读取SPRING配置文件XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //设置beanDefinitionReader服务于当前CONTEXT// resource loading environment.beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);//读取配置文件loadBeanDefinitions(beanDefinitionReader);} /*** Initialize the bean definition reader used for loading the bean* definitions of this context. Default implementation is empty.* <p>Can be overridden in subclasses, e.g. for turning off XML validation* or using a different XmlBeanDefinitionParser implementation.* @param beanDefinitionReader the bean definition reader used by this context* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidationMode* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass*/protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {} /*** Load the bean definitions with the given XmlBeanDefinitionReader.* <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;* therefore this method is just supposed to load and/or register bean definitions.* <p>Delegates to a ResourcePatternResolver for resolving location patterns* into Resource instances.* @throws org.springframework.beans.BeansException in case of bean registration errors* @throws java.io.IOException if the required XML document isn't found* @see #refreshBeanFactory* @see #getConfigLocations* @see #getResources* @see #getResourcePatternResolver*///读取配置文件protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {String[] configLocations = getConfigLocations();if (configLocations != null) {for (int i = 0; i < configLocations.length; i++) {reader.loadBeanDefinitions(configLocations[i]);}}} /*** The default location for the root context is "/WEB-INF/applicationContext.xml",* and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"* (like for a DispatcherServlet instance with the servlet-name "test").*///获得默认的ConfigLocationsprotected String[] getDefaultConfigLocations() {if (getNamespace() != null) {return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() +  DEFAULT_CONFIG_LOCATION_SUFFIX};}else {return new String[] {DEFAULT_CONFIG_LOCATION};}} 

原创粉丝点击