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; }
  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/xinzhuangzi/p/4100519.html
Copyright © 2011-2022 走看看