在上一篇Spring源碼閱讀——ClassPathXmlApplicationContext(二)文章的最後,須要解析bean元素,建立BeanDefinitionHolder實例、完成必須的裝配和進行最終的註冊bean來完成bean元素的解析和註冊,下面分別閱讀三步的源碼。node
BeanDefinitionHolder的建立是委託給BeanDefinitionParserDelegate這個代理類的parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)方法來完成的,此方法的實現以下:spring
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { // 獲取id屬性值 String id = ele.getAttribute(ID_ATTRIBUTE); // 獲取name屬性值 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); //解析name屬性值,將全部name放入List中 List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } // 賦值beanName爲id String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { // 若是id爲空,且name屬性不爲空,取第一個name爲beanName 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) { // 若是beanName爲空 if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { // 生成默認的beanName beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { // 生成默認的beanName beanName = this.readerContext.generateBeanName(beanDefinition); // 經過beanClass生成一個alias String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } // 獲得別名數組 String[] aliasesArray = StringUtils.toStringArray(aliases); // 建立BeanDefinitionHolder對象並返回 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
在上述源碼中,調用了parseBeanDefinitionElement(ele, beanName, containingBean)方法建立AbstractBeanDefinition 實例,下面是此方法的實現:segmentfault
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { // 根據beanName建立BeanEntry實體,而且push BeanEntry this.parseState.push(new BeanEntry(beanName)); // 獲取class屬性值 String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } // 獲取parent屬性值 String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { // 建立AbstractBeanDefinition實例 AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 設置AbstractBeanDefinition實例的其餘各類屬性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); // 獲取子元素description bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // 獲取子元素meta parseMetaElements(ele, bd); // 解析子元素lookup-method parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析子元素replaced-method parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析子元素constructor-arg 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 { // pop BeanEntry this.parseState.pop(); } return null; }
decorateBeanDefinitionIfRequired(ele, bdHolder)接口的最終實現以下:數組
public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; // 根據自定義屬性裝飾 // 獲取全部屬性 NamedNodeMap attributes = ele.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node node = attributes.item(i); finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } // 裝飾基於自定義嵌套元素的裝飾 // 獲取全部嵌套元素 NodeList children = ele.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition; }
此方法在存在非默認命名空間時,解析自定義的屬性和嵌套元素,decorateIfRequired(node, finalDefinition, containingBd)方法的實現以下:ide
public BeanDefinitionHolder decorateIfRequired( Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { // 獲取命名空間uri String namespaceUri = getNamespaceURI(node); // 若是不是默認命名空間uri if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { // 獲取命名空間handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler != null) { // 調用此handler 的decorate方法建立BeanDefinitionHolder實例 BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); if (decorated != null) { return decorated; } } else if (namespaceUri.startsWith("http://www.springframework.org/")) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); } else { // A custom namespace, not to be handled by Spring - maybe "xml:...". if (logger.isDebugEnabled()) { logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); } } } return originalDef; }
接下來是往註冊表中註冊bean,BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())的實現以下:學習
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { String beanName = definitionHolder.getBeanName(); // beanName 做爲key,註冊bean definition registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // beanName 做爲key,註冊alias String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
在SimpleBeanDefinitionRegistry類中,定義了註冊bean definition的Mam對象,map初始大小爲64,以下:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())ui
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "'beanName' must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); this.beanDefinitionMap.put(beanName, beanDefinition); }
經過這篇文章,學習了ClassPathXmlApplicationContext的啓動解析默認命名空間中元素的解析過程,下面繼續學習自定義命名空間中bean的解析。this