zoukankan      html  css  js  c++  java
  • 转:Spring技术内幕——深入解析Spring架构与设计原理(二)IOC实现原理

    这里使用 XmlBeanDefinitionReader来载入BeanDefinition到容器中,如以下代码清单所示:

    Java代码
    1.     //这里是调用的入口。  
    2.     public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {  
    3.         return loadBeanDefinitions(new EncodedResource(resource));  
    4.     }  
    5.     //这里是载入XML形式的BeanDefinition的地方。  
    6.     public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {  
    7.         Assert.notNull(encodedResource, "EncodedResource must not be null");  
    8.         if (logger.isInfoEnabled()) {  
    9.             logger.info("Loading XML bean definitions from " + encodedResource.getResource());  
    10.         }  
    11.   
    12.         Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();  
    13.         if (currentResources == null) {  
    14.             currentResources = new HashSet<EncodedResource>(4);  
    15.             this.resourcesCurrentlyBeingLoaded.set(currentResources);  
    16.         }  
    17.         if (!currentResources.add(encodedResource)) {  
    18.             throw new BeanDefinitionStoreException(  
    19.                     "Detected recursive loading of " + encodedResource + " - check your import definitions!");  
    20.         }  
    21.         //这里得到XML文件,并得到IO的InputSource准备进行读取。  
    22.         try {  
    23.             InputStream inputStream = encodedResource.getResource().getInputStream();  
    24.             try {  
    25.                 InputSource inputSource = new InputSource(inputStream);  
    26.                 if (encodedResource.getEncoding() != null) {  
    27.                     inputSource.setEncoding(encodedResource.getEncoding());  
    28.                 }  
    29.                 return doLoadBeanDefinitions(inputSource, encodedResource.getResource());  
    30.             }  
    31.             finally {  
    32.                 inputStream.close();  
    33.             }  
    34.         }  
    35.         catch (IOException ex) {  
    36.             throw new BeanDefinitionStoreException(  
    37.                     "IOException parsing XML document from " + encodedResource.getResource(), ex);  
    38.         }  
    39.         finally {  
    40.             currentResources.remove(encodedResource);  
    41.             if (currentResources.isEmpty()) {  
    42.                 this.resourcesCurrentlyBeingLoaded.set(null);  
    43.             }  
    44.         }  
    45.     }  
    46. //具体的读取过程可以在doLoadBeanDefinitions方法中找到:  
    47.     //这是从特定的XML文件中实际载入BeanDefinition的地方  
    48.     protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)  
    49.             throws BeanDefinitionStoreException {  
    50.         try {  
    51.             int validationMode = getValidationModeForResource(resource);  
    52.             //这里取得XML文件的Document对象,这个解析过程是由 documentLoader完成的,这个documentLoader是DefaultDocumentLoader,在定义documentLoader的地方创建  
    53.             Document doc = this.documentLoader.loadDocument(  
    54.                     inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());  
    55.             //这里启动的是对BeanDefinition解析的详细过程,这个解析会使用到Spring的Bean配置规则,是我们下面需要详细关注的地方。  
    56.             return registerBeanDefinitions(doc, resource);  
    57.         }  
    58.         catch (BeanDefinitionStoreException ex) {  
    59.             throw ex;  
    60.         }  
    61.         catch (SAXParseException ex) {  
    62.             throw new XmlBeanDefinitionStoreException(resource.getDescription(),  
    63.                     "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);  
    64.         }  
    65.         catch (SAXException ex) {  
    66.             throw new XmlBeanDefinitionStoreException(resource.getDescription(),  
    67.                     "XML document from " + resource + " is invalid", ex);  
    68.         }  
    69.         catch (ParserConfigurationException ex) {  
    70.             throw new BeanDefinitionStoreException(resource.getDescription(),  
    71.                     "Parser configuration exception parsing XML from " + resource, ex);  
    72.         }  
    73.         catch (IOException ex) {  
    74.             throw new BeanDefinitionStoreException(resource.getDescription(),  
    75.                     "IOException parsing XML document from " + resource, ex);  
    76.         }  
    77.         catch (Throwable ex) {  
    78.             throw new BeanDefinitionStoreException(resource.getDescription(),  
    79.                     "Unexpected exception parsing XML document from " + resource, ex);  
    80.         }  
    81.     }  
    //这里是调用的入口。 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } //这里是载入XML形式的BeanDefinition的地方。 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected recursive loading of " + encodedResource + " - check your import definitions!"); } //这里得到XML文件,并得到IO的InputSource准备进行读取。 try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.set(null); } } } //具体的读取过程可以在doLoadBeanDefinitions方法中找到: //这是从特定的XML文件中实际载入BeanDefinition的地方 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); //这里取得XML文件的Document对象,这个解析过程是由 documentLoader完成的,这个documentLoader是DefaultDocumentLoader,在定义documentLoader的地方创建 Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); //这里启动的是对BeanDefinition解析的详细过程,这个解析会使用到Spring的Bean配置规则,是我们下面需要详细关注的地方。 return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }
    关于具体的Spring BeanDefinition的解析,是在BeanDefinitionParserDelegate中完成的。这个类里包含了各种Spring Bean定义规则的处理,感兴趣的同学可以仔细研究。我们举一个例子来分析这个处理过程,比如我们最熟悉的对Bean元素的处理是怎样完成的,也就是我们 在XML定义文件中出现的<bean></bean>这个最常见的元素信息是怎样被处理的。在这里,我们会看到那些熟悉的 BeanDefinition定义的处理,比如id、name、aliase等属性元素。把这些元素的值从XML文件相应的元素的属性中读取出来以后,会 被设置到生成的BeanDefinitionHolder中去。这些属性的解析还是比较简单的。对于其他元素配置的解析,比如各种Bean的属性配置,通 过一个较为复杂的解析过程,这个过程是由parseBeanDefinitionElement来完成的。解析完成以后,会把解析结果放到 BeanDefinition对象中并设置到BeanDefinitionHolder中去,如以下清单所示:

    Java代码
    1. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {  
    2.         //这里取得在<bean>元素中定义的id、name和aliase属性的值  
    3.         String id = ele.getAttribute(ID_ATTRIBUTE);  
    4.         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);  
    5.   
    6.         List<String> aliases = new ArrayList<String>();  
    7.         if (StringUtils.hasLength(nameAttr)) {  
    8.             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);  
    9.             aliases.addAll(Arrays.asList(nameArr));  
    10.         }  
    11.   
    12.         String beanName = id;  
    13.         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {  
    14.             beanName = aliases.remove(0);  
    15.             if (logger.isDebugEnabled()) {  
    16.                 logger.debug("No XML 'id' specified - using '" + beanName +  
    17.                         "' as bean name and " + aliases + " as aliases");  
    18.             }  
    19.         }  
    20.   
    21.         if (containingBean == null) {  
    22.             checkNameUniqueness(beanName, aliases, ele);  
    23.         }  
    24.   
    25.         //这个方法会引发对bean元素的详细解析  
    26. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);  
    27.         if (beanDefinition != null) {  
    28.             if (!StringUtils.hasText(beanName)) {  
    29.                 try {  
    30.                     if (containingBean != null) {  
    31.                         beanName = BeanDefinitionReaderUtils.generateBeanName(  
    32.                                 beanDefinition, this.readerContext.getRegistry(), true);  
    33.                     }  
    34.                     else {  
    35.                         beanName = this.readerContext.generateBeanName(beanDefinition);  
    36.                         // Register an alias for the plain bean class name, if still possible,  
    37.                         // if the generator returned the class name plus a suffix.  
    38.                         // This is expected for Spring 1.2/2.0 backwards compatibility.  
    39.                         String beanClassName = beanDefinition.getBeanClassName();  
    40.                         if (beanClassName != null &&  
    41.                                 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&  
    42.                                 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {  
    43.                             aliases.add(beanClassName);  
    44.                         }  
    45.                     }  
    46.                     if (logger.isDebugEnabled()) {  
    47.                         logger.debug("Neither XML 'id' nor 'name' specified - " +  
    48.                                 "using generated bean name [" + beanName + "]");  
    49.                     }  
    50.                 }  
    51.                 catch (Exception ex) {  
    52.                     error(ex.getMessage(), ele);  
    53.                     return null;  
    54.                 }  
    55.             }  
    56.             String[] aliasesArray = StringUtils.toStringArray(aliases);  
    57.             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  
    58.         }  
    59.   
    60.         return null;  
    61.     }  
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //这里取得在<bean>元素中定义的id、name和aliase属性的值 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 (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } //这个方法会引发对bean元素的详细解析 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
  • 相关阅读:
    写写我的这几天,损失惨重
    ArcIMS9.0安装指南图解
    《亲爱的界面,让用户乐于使用、爱不释手》小编推介
    从图灵原创谈起,带你走进国产技术书的时代
    【民间图灵奖】读《图灵的秘密》写读后感获图灵水杯
    2012年的这些经典书目你读了没?
    2012年图灵技术图书大盘点
    就让推荐,系统实践起来吧!
    用编程工具实现数据可视化的几个选择
    你未必知道的CSS故事:揭开leading的面纱
  • 原文地址:https://www.cnblogs.com/xinzhuangzi/p/4100519.html
Copyright © 2011-2022 走看看