原文出自:http://cmsblogs.comjava
import 標籤解析完畢了,再看 Spring 中最複雜也是最重要的標籤 bean 標籤的解析過程。架構
在方法 parseDefaultElement()
中,若是遇到標籤 爲 bean 則調用 processBeanDefinition()
方法進行 bean 標籤解析,以下:ide
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
整個過程分爲四個步驟函數
BeanDefinitionParserDelegate.parseBeanDefinitionElement()
進行元素解析,解析過程當中若是失敗,返回 null,錯誤由 ProblemReporter
處理。若是解析成功則返回 BeanDefinitionHolder 實例 bdHolder。BeanDefinitionHolder 爲持有 name 和 alias 的 BeanDefinition。BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()
進行自定義標籤處理BeanDefinitionReaderUtils.registerBeanDefinition()
對 bdHolder 進行註冊先看方法 parseBeanDefinitionElement()
,以下:ui
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { // 解析 ID 屬性 String id = ele.getAttribute(ID_ATTRIBUTE); // 解析 name 屬性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // 分割 name 屬性 List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_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"); } } // 檢查 name 的惟一性 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // 解析 屬性,構造 AbstractBeanDefinition AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { // 若是 beanName 不存在,則根據條件構造一個 beanName if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); 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); // 封裝 BeanDefinitionHolder return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
這個方法尚未對 Bean 標籤進行解析,只是在解析動做以前作了一些功能架構,主要的工做有:this
parseBeanDefinitionElement()
對屬性進行解析並封裝成 GenericBeanDefinition 實例 beanDefinition這裏有必要說下 beanName 的命名規則:若是 id 不爲空,則 beanName = id;若是 id 爲空,可是 alias 不空,則 beanName 爲 alias 的第一個元素,若是二者都爲空,則根據默認規則來設置 beanName。debug
上面三個步驟第二個步驟爲核心方法,它主要承擔解析 Bean 標籤中全部的屬性值。以下:code
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; // 解析 class 屬性 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null; // 解析 parent 屬性 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { // 建立用於承載屬性的 GenericBeanDefinition 實例 AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 解析默認 bean 的各類屬性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); // 提取 description bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // 解析元數據 parseMetaElements(ele, bd); // 解析 lookup-method 屬性 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析 replaced-method 屬性 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析構造函數參數 parseConstructorArgElements(ele, bd); // 解析 property 子元素 parsePropertyElements(ele, bd); // 解析 qualifier 子元素 parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
到這裏,Bean 標籤的全部屬性咱們均可以看到其解析的過程,也就說到這裏咱們已經解析一個基本可用的 BeanDefinition。對象
因爲解析過程較爲漫長,篇幅較大,爲了更好的觀看體驗,將這篇博文進行拆分。下篇博客主要介紹 BeanDefinition,以及解析默認 Bean 的過程(parseBeanDefinitionAttributes()
)blog
--