【永恒的瞬間】
          ?Give me hapy ?
          web.xml

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          <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監(jiān)聽器 -->
            <listener>
              <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
            </listener>
          ?
            <!-- 定義SPRING監(jiān)聽器 -->
          
            <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>
          

          進(jìn)入contextLoaderListener看看到底加載時做了甚么
          ==>org.springframework.web.context.ContextLoaderListener

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          publicclass ContextLoaderListener implements ServletContextListener {
          ?
            private ContextLoader contextLoader;
          ?
            /**
             * Initialize the root web application context.
             *///當(dāng)WEB上下文初始化時,系統(tǒng)會調(diào)用此方法publicvoid contextInitialized(ServletContextEvent event) {
              this.contextLoader = createContextLoader();
          ?
          //監(jiān)聽到WEB上下文初始化的時候執(zhí)行SPRING上下文contextLoader的初始化工作
              this.contextLoader.initWebApplicationContext(event.getServletContext());
          }
          ?
            /**
             * Create the ContextLoader to use. Can be overridden in subclasses.
             * @return the new ContextLoader
             */protected ContextLoader createContextLoader() {returnnew ContextLoader();
            }
          ?
            /**
             * Return the ContextLoader used by this listener.
             */public ContextLoader getContextLoader() {return contextLoader;
            }
          ?
            /**
             * Close the root web application context.
             */publicvoid contextDestroyed(ServletContextEvent event) {if (this.contextLoader != null) {
                this.contextLoader.closeWebApplicationContext(event.getServletContext());
              }}
          ?
          }

          看一下是怎么來初始化webapplicationContext的
          ==>contextLoader.initWebApplicationContext

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
                throws IllegalStateException, BeansException {
          ?
              if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {thrownew 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.
          ?
          //創(chuàng)建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);

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          protected WebApplicationContext createWebApplicationContext(
                ServletContext servletContext, ApplicationContext parent) throws BeansException {//根據(jù)servletContext來決定要實例化的WebApplicationContext
              Class contextClass = determineContextClass(servletContext);
              if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {thrownew 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中設(shè)置的SPRING配置文件位置
              String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
              if (configLocation != null) {//把配置文件分段后設(shè)置到WebApplicationContext的ConfigLocations中
                wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
                    ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
              }//刷新WebApplicationContext
              wac.refresh();
          return wac;
            }

          ==>contextLoader.determineContextClass(servletContext);

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {//獲得需要實例化的CONTEXT類名,在web.xml中有設(shè)置,如果沒有設(shè)置,那么為空
              String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
              if (contextClassName != null) {try{return ClassUtils.forName(contextClassName);
                }catch (ClassNotFoundException ex) {thrownew ApplicationContextException(
                      "Failed to load custom context class [" + contextClassName + "]", ex);
                }}//如果在spring web.xml中沒有設(shè)置context類位置,那么取得默認(rèn)contextelse{//取得defaultStrategies配置文件中的WebApplicationContext屬性
                contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
                try{return ClassUtils.forName(contextClassName);
                }catch (ClassNotFoundException ex) {thrownew ApplicationContextException(
                      "Failed to load default context class [" + contextClassName + "]", ex);
                }}}

          SPRING上下文默認(rèn)的策略是甚么呢?
          ==>contextLoader.defaultStrategies

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          privatestaticfinal 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{//設(shè)置classpath為contextLoader同級目錄
                ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
                //加載該目錄下的所有properties文件
                defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
          }catch (IOException ex) {thrownew IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
              }}

          找到同級目錄下的配置文件
          ==>ContextLoader.properties

          1
          2
          3
          4
          5
          6
          7
          8
          # Default WebApplicationContext implementation classfor ContextLoader.
          # Used as fallback when no explicit context implementation has been specified as context-param.
          # Not meant to be customized by application developers.
          ?
          
          #默認(rèn)的WebApplicationContext為org.springframework.web.context.support.XmlWebApplicationContext
          org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
          

          ==>org.springframework.web.context.support.XmlWebApplicationContext
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          77
          78
          79
          80
          81
          82
          83
          84
          85
          86
          87
          88
          89
          90
          91
          92
          93
          publicclass XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
          ?
            /** Default config location for the root context */
          ?
          //配置了默認(rèn)的spring配置文件publicstaticfinal String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
          
          ?
            //配置文件默認(rèn)BUILD路徑publicstaticfinal String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
          ?
            //配置文件默認(rèn)后綴名publicstaticfinal 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配置protectedvoid loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {//從BEAN工廠獲得一個XmlBeanDefinitionReader 來讀取SPRING配置文件
              XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
          ?
              //設(shè)置beanDefinitionReader服務(wù)于當(dāng)前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
             */protectedvoid 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
             *///讀取配置文件protectedvoid 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").
             *///獲得默認(rèn)的ConfigLocationsprotected String[] getDefaultConfigLocations() {if (getNamespace() != null) {returnnew String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + 
          ?
          DEFAULT_CONFIG_LOCATION_SUFFIX};
              }else{returnnew String[] {DEFAULT_CONFIG_LOCATION};
              }}

          ==>AbstractBeanDefinitionReader.loadBeanDefinitions()

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          publicint loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
              ResourceLoader resourceLoader = getResourceLoader();
              if (resourceLoader == null) {thrownew BeanDefinitionStoreException(
                    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
              }
          ?
              if (resourceLoader instanceof ResourcePatternResolver) {// Resource pattern matching available.try{//根據(jù)配置文件讀取相應(yīng)配置
                  Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
          int loadCount = loadBeanDefinitions(resources);
                  if (logger.isDebugEnabled()) {
                    logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                  }return loadCount;
                }catch (IOException ex) {thrownew BeanDefinitionStoreException(
                      "Could not resolve bean definition resource pattern [" + location + "]", ex);
                }}else{// Can only load single resources by absolute URL.
                Resource resource = resourceLoader.getResource(location);
                int loadCount = loadBeanDefinitions(resource);
                if (logger.isDebugEnabled()) {
                  logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                }return loadCount;
              }}

          這個是其中一個ResourceLoader的實現(xiàn)
          ==>PathMatchingResourcePatternResolver.getResources(String locationPattern);

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          public Resource[] getResources(String locationPattern) throws IOException {
              Assert.notNull(locationPattern, "Location pattern must not be null");
              if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {// a class path resource (multiple resources for same name possible)if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {// a class path resource patternreturn findPathMatchingResources(locationPattern);
                }else{// all class path resources with the given namereturn findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
                }}else{// Only look for a pattern after a prefix here// (to not get fooled by a pattern symbol in a strange prefix).int prefixEnd = locationPattern.indexOf(":") + 1;
                if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {// a file patternreturn findPathMatchingResources(locationPattern);
                }else{// a single resource with the given namereturnnew Resource[] {getResourceLoader().getResource(locationPattern)};
                }}}


          ==>PathMatchingResourcePatternResolver.findPathMatchingResources(String locationPattern);

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
              String rootDirPath = determineRootDir(locationPattern);
              String subPattern = locationPattern.substring(rootDirPath.length());
              Resource[] rootDirResources = getResources(rootDirPath);
          //collectionFactory初始化一個set容量為16
              Set result = CollectionFactory.createLinkedSetIfPossible(16);
              for (int i = 0; i < rootDirResources.length; i++) {
                Resource rootDirResource = rootDirResources[i];
                if (isJarResource(rootDirResource)) {
                  result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
                }else{
                  result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
                }}if (logger.isDebugEnabled()) {
                logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
              }return (Resource[]) result.toArray(new Resource[result.size()]);
            }


          前面說到有一個刷新WebApplicationContext的操作,但是XmlWebApplicationContext 并沒有實現(xiàn)refresh方法,而方法的實現(xiàn)寫在

          AbstractRefreshableWebApplicationContext 中

          ==>AbstractRefreshableWebApplicationContext.refresh();
          1
          2
          3
          4
          5
          6
          7
          publicvoid refresh() throws BeansException {if (ObjectUtils.isEmpty(getConfigLocations())) {//設(shè)置configLocations為默認(rèn)的getDefaultConfigLocations()
                setConfigLocations(getDefaultConfigLocations());
              }
              super.refresh();
            }


          ==>AbstractApplicationContext.refresh();
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          77
          78
          publicvoid refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {
                this.startupTime = System.currentTimeMillis();
          ?
                synchronized (this.activeMonitor) {
                  this.active = true;
                }
          ?
                // Tell subclass to refresh the internal bean factory.
                refreshBeanFactory();
                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
          ?
                // Tell the internal bean factory to use the context's class loader.
                beanFactory.setBeanClassLoader(getClassLoader());
          ?
                // Populate the bean factory with context-specific resource editors.
                beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
          ?
                // Configure the bean factory with context semantics.
                beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
                beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
                beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
                beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
                beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
          ?
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
          ?
                // Invoke factory processors registered with the context instance.for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
                  BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
                  factoryProcessor.postProcessBeanFactory(beanFactory);
                }
          ?
                if (logger.isInfoEnabled()) {if (getBeanDefinitionCount() == 0) {
                    logger.info("No beans defined in application context [" + getDisplayName() + "]");
                  }else{
                    logger.info(getBeanDefinitionCount() + " beans defined in application context [" + 
          ?
          getDisplayName() + "]");
                  }}
          ?
                try{// Invoke factory processors registered as beans in the context.
                  invokeBeanFactoryPostProcessors();
          ?
                  // Register bean processors that intercept bean creation.
                  registerBeanPostProcessors();
          ?
                  // Initialize message source for this context.
                  initMessageSource();
          ?
                  // Initialize event multicaster for this context.
                  initApplicationEventMulticaster();
          ?
                  // Initialize other special beans in specific context subclasses.
                  onRefresh();
          ?
                  // Check for listener beans and register them.
                  registerListeners();
          ?
                  // Instantiate singletons this late to allow them to access the message source.
                  beanFactory.preInstantiateSingletons();
          ?
                  // Last step: publish corresponding event.
                  publishEvent(new ContextRefreshedEvent(this));
                }
          ?
                catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.
                  beanFactory.destroySingletons();
                  throw ex;
                }}}
          posted on 2007-01-12 16:53 ???MengChuChen 閱讀(2557) 評論(0)  編輯  收藏 所屬分類: Spring
          主站蜘蛛池模板: 南江县| 江油市| 阜新市| 汤原县| 阿城市| 蓝山县| 柘荣县| 阳江市| 新宾| 罗平县| 同德县| 博乐市| 黄浦区| 竹溪县| 始兴县| 南靖县| 公安县| 德兴市| 宁波市| 丰原市| 临夏市| 宾川县| 泰宁县| 滦南县| 易门县| 长兴县| 雷波县| 明水县| 威远县| 延吉市| 大丰市| 独山县| 临漳县| 清新县| 黔西县| 彭阳县| 昌江| 寿阳县| 长兴县| 济源市| 章丘市|