服务器启动,加载web.xml 文件的时候发现监听器:ContextLoaderListener
初始化监听器 
1所以调用contextInitialized方法

@Override 

 public void contextInitialized(ServletContextEvent event) { 

    initWebApplicationContext(event.getServletContext()); 

 } 

 initWebApplicationContext 代码如下 

 public WebApplicationContext initWebApplicationContext(ServletContext 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); 

          } 

       } 

      。。。。。。 

       return this.context; 

    } 

 } 

 2调用了configureAndRefreshWebApplicationContext方法: 

 protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { 

    。。。。。 

    wac.refresh(); 

 } 

 3调用refresh()方法: 

 @Override 

 public void refresh() throws BeansException, IllegalStateException { 

    synchronized (this.startupShutdownMonitor) { 

       // Prepare this context for refreshing. 

       prepareRefresh(); 



       // Tell the subclass to refresh the internal bean factory. 

       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 

 。。。。。。。。 

       

    } 

 } 

 4 调用obtainFreshBeanFactory()方法 

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 

    refreshBeanFactory(); 

    ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 

    if (logger.isDebugEnabled()) { 

       logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); 

    } 

    return beanFactory; 

 } 

 5 之后调用到refreshBeanFactory()方法 

 @Override 

 protected final void refreshBeanFactory() throws BeansException { 

    if (hasBeanFactory()) { 

       destroyBeans(); 

       closeBeanFactory(); 

    } 

    try { 

       DefaultListableBeanFactory beanFactory = createBeanFactory(); 

       beanFactory.setSerializationId(getId()); 

       customizeBeanFactory(beanFactory); 

       loadBeanDefinitions(beanFactory); 

       synchronized (this.beanFactoryMonitor) { 

          this.beanFactory = beanFactory; 

       } 

    } 

    catch (IOException ex) { 

       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 

    } 

 } 

 6 调用loadBeanDefinitions()方法 

 @Override 

 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { 

    // Create a new XmlBeanDefinitionReader for the given BeanFactory. 

    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 



    // Configure the bean definition reader with this context's 

    // resource loading environment. 

    beanDefinitionReader.setEnvironment(getEnvironment()); 

    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); 

 } 

 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { 

    String[] configLocations = getConfigLocations(); 

    if (configLocations != null) { 

       for (String configLocation : configLocations) { 

          reader.loadBeanDefinitions(configLocation); 

       } 

    } 

 } 



 Spring加载资源分析 

 说明: 

     这篇文档是对Spring加载和解析xml文件过程的分析,下面看一个spring解析xml文件的测试例子。 

     @Test 

     public void test3BeanDefinitionReader(){ 

         DefaultResourceLoader loader = new DefaultResourceLoader(); 

         Resource resource = loader.getResource("/ioc/application.xml"); 

         BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); 

         BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry); 

         

         int count = reader.loadBeanDefinitions(resource); 

         String[] beanDefinitionNames = reader.getRegistry().getBeanDefinitionNames(); 

         System.out.println("----------------------"); 

         for (String name : beanDefinitionNames) { 

             System.out.println(name); 

         } 

     } 

 大概的逻辑:先读取文件放到doc 里,然后 解析doc ,一个元素一个元素,拿出来,解析 生成 bean ,然后放入registry 中。 





 Spring解析配置文件中用到的一些关键类的介绍: 

 Resource:各种资源的抽象接口,包括xml文件,网络上的资源等。 

 BeanDefinitionRegistry:用于注册Bean。 

 BeanDefinitionReader:用于读取解析Resource的抽象接口。 

 DefaultBeanDefinitionDocumentReader:实现了BeanDefinitionDocumentReader接口,DefaultBeanDefinitionDocumentReader并不负责任何具体的bean解析,它面向的是xml Document对象,根据其元素的命名空间和名称,起一个类似路由的作用((不过,命名空间的判断,也是委托给delegate来做的),它跟BeanDefinitionParserDelegate协同合作,把解析任务交接BeanDefinitionParserDelegate来做。 

 BeanDefinitionParserDelegate:完成具体Bean的解析(比如<bean>、<import>、<alias>标签),对于扩展的标签会交给不同的NamespaceHandler跟BeanDefinitionParser来解析。 

 BeanDefinitionParser:解析配置文件成相应的BeanDefinition(<context:component-scan>,<aop:config>等标签都是又不同的BeanDefinitionParser来解析),一般在NamespaceHandler中使用。Spring也为自定义BeanDefinitionParser提供了很多支持,在一些抽象类的基础上添加少量功能即可满足大部分需求。 

 NamespaceHandler:要解析自定义的bean就要通过自己所实现的NamespaceHandler来进行解析。比如定义了http\://www.springframework.org/schema/osgi=org.springframework.osgi.config.OsgiNamespaceHandler,那么在碰到osgi的scheme的时候就会去调用OsgiNamespaceHandler来进行解析; 在对于普通的扩展需求来说,只要让自己的Handler继承NamespaceHandlerSupport并实现 init()方法 就好了,对于特殊的扩展需求 则可以自己 来实现NamespaceHandler。 





 下面来分析一下源代码: 

 源码1:加载xml文件 

 XmlBeanDefinitionReader: 

     public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { 

         //加载xml资源 

         return loadBeanDefinitions(new EncodedResource(resource)); 

     } 

   

     public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 

              

             InputStream inputStream = encodedResource.getResource().getInputStream(); 

             try { 

                 InputSource inputSource = new InputSource(inputStream); 

                 if (encodedResource.getEncoding() != null) { 

                     //设置字符集 

                     inputSource.setEncoding(encodedResource.getEncoding()); 

                 } 

                 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 

             } 



     } 



     protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) 

             throws BeanDefinitionStoreException { 

         try { 

             int validationMode = getValidationModeForResource(resource); 

             //根据xml文件,得到标准的Document对象 

             Document doc = this.documentLoader.loadDocument( 

                     inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); 

             return registerBeanDefinitions(doc, resource); 



     } 

   

     public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { 

         //BeanDefinitionDocumentReader实际解析doc文档 

         BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 

         int countBefore = getRegistry().getBeanDefinitionCount(); 

         documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 

         return getRegistry().getBeanDefinitionCount() - countBefore; 

     } 

   

 DefaultBeanDefinitionDocumentReader: 

     public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 



         Element root = doc.getDocumentElement(); 

         //元素解析的代理类,主要的bean解析,以及一些自定义元素的解析 

         BeanDefinitionParserDelegate delegate = createHelper(readerContext, root); 

         //默认为空操作 

         preProcessXml(root); 

         //解析元素 

         parseBeanDefinitions(root, delegate); 

         postProcessXml(root); 

     } 

   

     protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 

         //默认命名空间为http://www.springframework.org/schema/beans,也就是xml文件中<bean>的标签 

         if (delegate.isDefaultNamespace(root)) { 

             NodeList nl = root.getChildNodes(); 

             for (int i = 0; i < nl.getLength(); i++) { 

                 Node node = nl.item(i); 

                 if (node instanceof Element) { 

                     Element ele = (Element) node; 

                     if (delegate.isDefaultNamespace(ele)) { 

                         //处理默认<bean>标签 

                         parseDefaultElement(ele, delegate); 

                     } 

                     else { 

                         //处理自定义标签 (i.e.  AOP,CONTENT,JDBC) 

                         delegate.parseCustomElement(ele); 

                     } 

                 } 

             } 

         } 

         else {//处理自定义标签 

             delegate.parseCustomElement(root); 

         } 

     } 



 源码2:基本元素解析(i.e.  <bean>、<import>......) 

 DefaultBeanDefinitionDocumentReader: 

     private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 

         if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 

             //解析<import>标签 

             importBeanDefinitionResource(ele); 

         } 

         else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { 

             //解析<alias>标签 

             processAliasRegistration(ele); 

         } 

         else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { 

             //解析<bean>标签 

             processBeanDefinition(ele, delegate); 

         } 

     } 

   

     protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { 

         //解析element,得到BeanDefinition,BeanDefinitionHolder中包含了BeanDefinition 

         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 



                 //注册BeanDefinition 

                 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 



     } 

   

 BeanDefinitionParserDelegate: 

     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { 

         return parseBeanDefinitionElement(ele, null); 

     } 

   

 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { 

         String id = ele.getAttribute(ID_ATTRIBUTE); 

         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 

         List<String> aliases = new ArrayList<String>(); 

         if (StringUtils.hasLength(nameAttr)) { 

             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS); 

             aliases.addAll(Arrays.asList(nameArr)); 

         } 

         String beanName = id; 



         if (containingBean == null) { 

             //检查bean name的唯一性 

             checkNameUniqueness(beanName, aliases, ele); 

         } 

         //解析Element 

         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 

         if (beanDefinition != null) { 



             String[] aliasesArray = StringUtils.toStringArray(aliases); 

             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 

         } 

         return null; 

     } 

   

 //真正解析<bean>的地方 

 public AbstractBeanDefinition parseBeanDefinitionElement( 

             Element ele, String beanName, BeanDefinition containingBean) { 

         this.parseState.push(new BeanEntry(beanName)); 

         String className = null; 

         if (ele.hasAttribute(CLASS_ATTRIBUTE)) { 

             className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); 

         } 



             String parent = null; 

             if (ele.hasAttribute(PARENT_ATTRIBUTE)) { 

                 parent = ele.getAttribute(PARENT_ATTRIBUTE); 

             } 

             AbstractBeanDefinition bd = createBeanDefinition(className, parent); 

             parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); 

             bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); 

             parseMetaElements(ele, bd); 

             parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); 

             parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); 

             parseConstructorArgElements(ele, bd); 

             parsePropertyElements(ele, bd); 

             parseQualifierElements(ele, bd); 

             bd.setResource(this.readerContext.getResource()); 

             bd.setSource(extractSource(ele)); 

             return bd; 



         return null; 

     } 



 源码3:处理扩展或自定义标签: 

 BeanDefinitionParserDelegate: 

     public BeanDefinition parseCustomElement(Element ele) { 

         return parseCustomElement(ele, null); 

     } 



     public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { 

         String namespaceUri = getNamespaceURI(ele); 

         //根据元素的命名空间得到NamespaceHandler 

         NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 



         //使用合适的NamespaceHandler解析元素 

         return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); 

     } 



 NamespaceHandlerSupport: 

     public BeanDefinition parse(Element element, ParserContext parserContext) { 

         //得到真正具体处理自定义的BeanDefinitionParser,解析element得到BeanDefinition 

         return findParserForElement(element, parserContext).parse(element, parserContext); 

     } 





     private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { 

         String localName = parserContext.getDelegate().getLocalName(element); 

         //parsers中包含了具体处理自定义标签的类 

         BeanDefinitionParser parser = this.parsers.get(localName); 



         return parser; 

     } 





 代码3.2:在源码3.1中代码:{NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri)}这步中,展示了对于扩展或自定义的标签的处理类是从哪里加载的 

    public NamespaceHandler resolve(String namespaceUri) { 

         //得到Map<Element名称,NamespaceHandler处理类> 

         Map<String, Object> handlerMappings = getHandlerMappings(); 

         //根据namespaceUri得到匹配的NamespaceHandler 

         Object handlerOrClassName = handlerMappings.get(namespaceUri); 

         if (handlerOrClassName == null) { 

             return null; 

         } 

         else if (handlerOrClassName instanceof NamespaceHandler) { 

             return (NamespaceHandler) handlerOrClassName; 

         }else{ 



                 } 

     } 



     private Map<String, Object> getHandlerMappings() { 



 //handlerMappingsLocation默认值:META-INF/spring.handlers 

 //spring就会从jar包中的Meta-INF/spring.handlers文件中得到处理各种不同命名空间元素的类 

                         Properties mappings = 

                                 PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); 



                         Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(); 

                         CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); 

                         this.handlerMappings = handlerMappings; 



         return this.handlerMappings; 

     }



      当初一直在想Spring是如何解析自定义元素(i.e. <context:component-scan>,<aop:config> )。通过源码分析看出spring在解析的过程中,会去收集spring.*.jar/META-INF下的spring.handers,spring.schemas文件,这2个文件就是指明了解析spring中自定义标签的Namespace类。如果自己开发Spring组件,需要增加新的标签,也可以按照这个机制。