接着上文的內容,咱們經歷了xml資源文件的校驗/解析/終於要進入到Bean的加載中了。node
上文進行到:spring
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 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)) { this.parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
這裏,加載代理類的一個判斷是不是默認命名空間的標籤,把過程分爲兩個步驟,咱們先來看第一個分支,即默認標籤的解析。緩存
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, "import")) { this.importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, "alias")) { this.processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, "bean")) { this.processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, "beans")) { this.doRegisterBeanDefinitions(ele); } }
默認的這幾個根標籤的解析,咱們就從最關注的"bean"標籤解析開始吧。即:this.processBeanDefinition(ele, delegate)。架構
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // 1 if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); // 2 try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry()); // 3 } catch (BeanDefinitionStoreException var5) { this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5); } this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); // 4 } }
這裏分爲幾個步驟:ide
1: 把ele元素解析爲咱們須要的 BeanDefinitionHolder 對象。函數
2: 判斷子元素中,是否有自定義標籤,若是有調用自定義標籤的處理Handle進行處理,並獲取返回的bdHolderui
3: 將解析到的bdHolder註冊到咱們的配置讀取上下文的註冊表中this
4: 觸發Bean註冊完成的事件通知spa
理完思路,那咱們就從第一個步驟開始,即把ele xml節點翻譯成咱們的BeanDefinition對象。架構設計
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute("id"); String nameAttr = ele.getAttribute("name"); List<String> aliases = new ArrayList(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; "); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(id) && !aliases.isEmpty()) { beanName = (String)aliases.remove(0); if (this.logger.isDebugEnabled()) { this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { this.checkNameUniqueness(beanName, aliases, ele); } AbstractBeanDefinition beanDefinition = this.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); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (this.logger.isDebugEnabled()) { this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]"); } } catch (Exception var9) { this.error(var9.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } else { return null; } }
這裏首先獲取AbstractBeanDefinition對象,而後組裝成BeanDefinitionHolder。查看parseBeanDefinitionElement 的代碼
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute("class")) { className = ele.getAttribute("class").trim(); } try { String parent = null; if (ele.hasAttribute("parent")) { parent = ele.getAttribute("parent"); } AbstractBeanDefinition bd = this.createBeanDefinition(className, parent); this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description")); this.parseMetaElements(ele, bd); this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); this.parseConstructorArgElements(ele, bd); this.parsePropertyElements(ele, bd); this.parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(this.extractSource(ele)); AbstractBeanDefinition var7 = bd; return var7; } catch (ClassNotFoundException var13) { this.error("Bean class [" + className + "] not found", ele, var13); } catch (NoClassDefFoundError var14) { this.error("Class that bean class [" + className + "] depends on not found", ele, var14); } catch (Throwable var15) { this.error("Unexpected failure during bean definition parsing", ele, var15); } finally { this.parseState.pop(); } return null; }
看這句createBeanDefinition(className, parent),跟進代碼到BeanDefinitionReaderUtils的createBeanDefinition方法
public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); if (className != null) { if (classLoader != null) { bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; }
這裏建立的是一個GenericBeanDefinition對象。AbstractBeanDefinition一共有三個子類
GenericBeanDefinition
ChildBeanDefinition
RootBeanDefinition
暫時沒看到Root和Child的應用,咱們這裏就只關注下這個GenericBeanDefinition。className不爲空,classLoader爲空,那麼只設置下BeanCassName屬性。
繼續解析:
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { if (ele.hasAttribute("singleton")) { this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } else if (ele.hasAttribute("scope")) { bd.setScope(ele.getAttribute("scope")); } else if (containingBean != null) { bd.setScope(containingBean.getScope()); } if (ele.hasAttribute("abstract")) { bd.setAbstract("true".equals(ele.getAttribute("abstract"))); } String lazyInit = ele.getAttribute("lazy-init"); if ("default".equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit("true".equals(lazyInit)); String autowire = ele.getAttribute("autowire"); bd.setAutowireMode(this.getAutowireMode(autowire)); String dependencyCheck = ele.getAttribute("dependency-check"); bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck)); String autowireCandidate; if (ele.hasAttribute("depends-on")) { autowireCandidate = ele.getAttribute("depends-on"); bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; ")); } autowireCandidate = ele.getAttribute("autowire-candidate"); String destroyMethodName; if (!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) { bd.setAutowireCandidate("true".equals(autowireCandidate)); } else { destroyMethodName = this.defaults.getAutowireCandidates(); if (destroyMethodName != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } if (ele.hasAttribute("primary")) { bd.setPrimary("true".equals(ele.getAttribute("primary"))); } if (ele.hasAttribute("init-method")) { destroyMethodName = ele.getAttribute("init-method"); if (!"".equals(destroyMethodName)) { bd.setInitMethodName(destroyMethodName); } } else if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } if (ele.hasAttribute("destroy-method")) { destroyMethodName = ele.getAttribute("destroy-method"); if (!"".equals(destroyMethodName)) { bd.setDestroyMethodName(destroyMethodName); } } else if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } if (ele.hasAttribute("factory-method")) { bd.setFactoryMethodName(ele.getAttribute("factory-method")); } if (ele.hasAttribute("factory-bean")) { bd.setFactoryBeanName(ele.getAttribute("factory-bean")); } return bd; }
這裏解析各類bd的屬性,並設置到bd對象裏。這些屬性好比init-method / destroy-method / lazy-init 這些咱們常常使用的,還有些不熟悉的,能夠到時候用到的時候查看了解下。
下面解析META元素:
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) { NodeList nl = ele.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "meta")) { Element metaElement = (Element)node; String key = metaElement.getAttribute("key"); String value = metaElement.getAttribute("value"); BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); attribute.setSource(this.extractSource(metaElement)); attributeAccessor.addMetadataAttribute(attribute); } } }
遍歷全部meta標籤,建立BeanMetaAttribute屬性,並添加到bd中,這裏向上轉型到了BeanMetadataAttributeAccessor類。這裏仍是很清晰的,接口該作什麼事情,仍是分開的很清楚的。這裏是架構設計裏 接口隔離原則的體現。不一樣接口裏,作的事情是不同的,並不混在一塊兒,這樣當一個部分須要改動的時候,不會影響另外一個部分。個人理解。
繼續:解析lookup-method元素
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) { NodeList nl = beanEle.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) { Element ele = (Element)node; String methodName = ele.getAttribute("name"); String beanRef = ele.getAttribute("bean"); LookupOverride override = new LookupOverride(methodName, beanRef); override.setSource(this.extractSource(ele)); overrides.addOverride(override); } } }
添加到db的overrides屬性裏了。
解析:replaced-method 根look-method標籤相似再也不贅述
解析:constructor-arg 標籤,構造函數標籤比較常見,這裏也相對複雜些,至少從代碼上看
public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) { NodeList nl = beanEle.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "constructor-arg")) { this.parseConstructorArgElement((Element)node, bd); } } }
先遍歷元素,而後具體的操做,由parseConstructorArgElement方法來負責
public void parseConstructorArgElement(Element ele, BeanDefinition bd) { String indexAttr = ele.getAttribute("index"); String typeAttr = ele.getAttribute("type"); String nameAttr = ele.getAttribute("name"); if (StringUtils.hasLength(indexAttr)) { try { int index = Integer.parseInt(indexAttr); if (index < 0) { this.error("'index' cannot be lower than 0", ele); } else { try { this.parseState.push(new ConstructorArgumentEntry(index)); Object value = this.parsePropertyValue(ele, bd, (String)null); ValueHolder valueHolder = new ValueHolder(value); if (StringUtils.hasLength(typeAttr)) { valueHolder.setType(typeAttr); } if (StringUtils.hasLength(nameAttr)) { valueHolder.setName(nameAttr); } valueHolder.setSource(this.extractSource(ele)); if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) { this.error("Ambiguous constructor-arg entries for index " + index, ele); } else { bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); } } finally { this.parseState.pop(); } } } catch (NumberFormatException var19) { this.error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele); } } else { try { this.parseState.push(new ConstructorArgumentEntry()); Object value = this.parsePropertyValue(ele, bd, (String)null); ValueHolder valueHolder = new ValueHolder(value); if (StringUtils.hasLength(typeAttr)) { valueHolder.setType(typeAttr); } if (StringUtils.hasLength(nameAttr)) { valueHolder.setName(nameAttr); } valueHolder.setSource(this.extractSource(ele)); bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); } finally { this.parseState.pop(); } } }
先獲取index/type/name屬性,而後根據有沒有index屬性類分別處理
若是有index屬性,那麼獲取value,並建立valueHolder最終添加到constructorArgumentValues 中。
來看具體的獲取value的過程
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { String elementName = propertyName != null ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> element"; NodeList nl = ele.getChildNodes(); Element subElement = null; for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) { if (subElement != null) { this.error(elementName + " must not contain more than one sub-element", ele); } else { subElement = (Element)node; } } } boolean hasRefAttribute = ele.hasAttribute("ref"); boolean hasValueAttribute = ele.hasAttribute("value"); if (hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) { this.error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele); } if (hasRefAttribute) { String refName = ele.getAttribute("ref"); if (!StringUtils.hasText(refName)) { this.error(elementName + " contains empty 'ref' attribute", ele); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(this.extractSource(ele)); return ref; } else if (hasValueAttribute) { TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value")); valueHolder.setSource(this.extractSource(ele)); return valueHolder; } else if (subElement != null) { return this.parsePropertySubElement(subElement, bd); } else { this.error(elementName + " must specify a ref or value", ele); return null; } }
獲取value的過程分爲幾個主要部分,根據是ref類型,仍是value類型不一樣,或者是子元素類型,操做不一樣
若是是ref類型,建立RuntimeBeanReference對象;若是是value類型,則封裝爲TypedStringVlue類型。若是是子元素類型,則繼續由parsePropertySubElement處理
public Object parsePropertySubElement(Element ele, BeanDefinition bd) { return this.parsePropertySubElement(ele, bd, (String)null); } public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) { if (!this.isDefaultNamespace((Node)ele)) { return this.parseNestedCustomElement(ele, bd); } else if (this.nodeNameEquals(ele, "bean")) { BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd); if (nestedBd != null) { nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd); } return nestedBd; } else if (this.nodeNameEquals(ele, "ref")) { String refName = ele.getAttribute("bean"); boolean toParent = false; if (!StringUtils.hasLength(refName)) { refName = ele.getAttribute("local"); if (!StringUtils.hasLength(refName)) { refName = ele.getAttribute("parent"); toParent = true; if (!StringUtils.hasLength(refName)) { this.error("'bean', 'local' or 'parent' is required for <ref> element", ele); return null; } } } if (!StringUtils.hasText(refName)) { this.error("<ref> element contains empty target attribute", ele); return null; } else { RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); ref.setSource(this.extractSource(ele)); return ref; } } else if (this.nodeNameEquals(ele, "idref")) { return this.parseIdRefElement(ele); } else if (this.nodeNameEquals(ele, "value")) { return this.parseValueElement(ele, defaultValueType); } else if (this.nodeNameEquals(ele, "null")) { TypedStringValue nullHolder = new TypedStringValue((String)null); nullHolder.setSource(this.extractSource(ele)); return nullHolder; } else if (this.nodeNameEquals(ele, "array")) { return this.parseArrayElement(ele, bd); } else if (this.nodeNameEquals(ele, "list")) { return this.parseListElement(ele, bd); } else if (this.nodeNameEquals(ele, "set")) { return this.parseSetElement(ele, bd); } else if (this.nodeNameEquals(ele, "map")) { return this.parseMapElement(ele, bd); } else if (this.nodeNameEquals(ele, "props")) { return this.parsePropsElement(ele); } else { this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } }
這裏能夠看到,全部支持的子類的分類處理都有了,裏邊的具體內容,就感興趣的進去看了。
2019-07-01 15:11繼續:
構造函數元素的解析說完了,咱們繼續主線解析到db中的,property元素的解析
public void parsePropertyElements(Element beanEle, BeanDefinition bd) { NodeList nl = beanEle.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "property")) { this.parsePropertyElement((Element)node, bd); } } }
public void parsePropertyElement(Element ele, BeanDefinition bd) { String propertyName = ele.getAttribute("name"); if (!StringUtils.hasLength(propertyName)) { this.error("Tag 'property' must have a 'name' attribute", ele); } else { this.parseState.push(new PropertyEntry(propertyName)); try { if (!bd.getPropertyValues().contains(propertyName)) { Object val = this.parsePropertyValue(ele, bd, propertyName); PropertyValue pv = new PropertyValue(propertyName, val); this.parseMetaElements(ele, pv); pv.setSource(this.extractSource(ele)); bd.getPropertyValues().addPropertyValue(pv); return; } this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele); } finally { this.parseState.pop(); } } }
這裏,跟構造函數的property元素解析不一樣的是,這裏是構造了PropertyValue對象,並添加到bd的propertyValues裏了。
qualifier元素解析
public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) { NodeList nl = beanEle.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "qualifier")) { this.parseQualifierElement((Element)node, bd); } } }
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) { String typeName = ele.getAttribute("type"); if (!StringUtils.hasLength(typeName)) { this.error("Tag 'qualifier' must have a 'type' attribute", ele); } else { this.parseState.push(new QualifierEntry(typeName)); try { AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName); qualifier.setSource(this.extractSource(ele)); String value = ele.getAttribute("value"); if (StringUtils.hasLength(value)) { qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value); } NodeList nl = ele.getChildNodes(); for(int i = 0; i < nl.getLength(); ++i) { Node node = nl.item(i); if (this.isCandidateElement(node) && this.nodeNameEquals(node, "attribute")) { Element attributeEle = (Element)node; String attributeName = attributeEle.getAttribute("key"); String attributeValue = attributeEle.getAttribute("value"); if (!StringUtils.hasLength(attributeName) || !StringUtils.hasLength(attributeValue)) { this.error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle); return; } BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue); attribute.setSource(this.extractSource(attributeEle)); qualifier.addMetadataAttribute(attribute); } } bd.addQualifier(qualifier); } finally { this.parseState.pop(); } } }
構造Qualifier對象,並添加到bd的qualifier屬性中。
到這裏,從ele文檔元素到BeanDefinition對象的解析基本就完成了。
咱們梳理下大體的思路,其實就是解析各類元素,針對不一樣元素或是生成bd的屬性,或是添加到對應的屬性列表中,總之ele要徹底轉換成咱們後續須要使用的BeanDefinition中。
下面,作了這麼多解析工做,咱們來完整的看一下BeanDefinition的屬性
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { public static final String SCOPE_DEFAULT = ""; // 省略部分靜態變量及final常量
private String scope = SCOPE_DEFAULT; // bean的做用域範圍,對應bean屬性scope private boolean abstractFlag; // 是不是抽象,對應bean屬性abstract private boolean lazyInit; // 是否延遲加載,對應bean屬性lazy-init private int autowireMode; // 自動注入模式 AUTOWIRE_NO AUTOWIRE_BY_NAME AUTOWIRE_BY_TYPE AUTOWIRE_CONSTRUCTOR private int dependencyCheck; // 依賴檢查,spring3.0後棄用 private String[] dependsOn; // 表示一個bean的實例化依靠另外一個bean先實例化,對應bean的屬性depend-on private boolean autowireCandidate; // autowireCandiate屬性設置爲false,這樣容器在查找自動裝配對象時,將不考慮該bean,即它不會考慮做爲其餘bean自動裝配的候選者,可是該bean自己可使用自動化裝配來注入其餘bean private boolean primary; // 自動裝配時,若是出現多個bean候選者,將做爲首選者,對應baen屬性primary private final Map<String, AutowireCandidateQualifier> qualifiers; // 用於記錄Qualifier,對應子元素qualifier private boolean nonPublicAccessAllowed; // 容許訪問非公開的構造起和方法,程序設置 private boolean lenientConstructorResolution; // 是否以寬鬆模式解析構造函數,默認爲true private ConstructorArgumentValues constructorArgumentValues; // 記錄構造函數注入屬性,對應bean屬性constructor-arg private MutablePropertyValues propertyValues; // 普通屬性集合 private MethodOverrides methodOverrides; // 方法重寫持有者,記錄lookup-method/ replace-method元素 private String factoryBeanName; // 用於bean屬性factoryBean private String factoryMethodName; // 對應bean屬性factory-method private String initMethodName; // 初始化方法,對應bean屬性init-method private String destroyMethodName; // 銷燬方法,對應bean屬性destroy-method private boolean enforceInitMethod; // 是否執行init-method,程序設置 private boolean enforceDestroyMethod; // 是否執行destroy-method,程序設置 private boolean synthetic; // 是不是用戶定義的而不是應用程序自己定義的,建立AOP時候爲true,程序設置 private int role; // 定義bean的應用,APPLICATION:用戶/ INFRASTRUCTURE:徹底內部使用,與用戶無關/ SUPPORT某些複雜配置的一部分,程序設置 private String description; // bean描述信息 private Resource resource; // 這個bean定義的資源
以上有些元素其實沒怎麼使用過,不是太熟悉,這些內容主要參考了《spring源碼深度解析》- 郝佳著
OK,咱們回到以前bean解析的代碼再來繼續:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException var5) { this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5); } this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
咱們以前重點都是在delegate.parseBeanDefinitionElement 的解析說明上,咱們繼續下邊這句
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder) ,根據方法的名稱,其實大概能夠判斷意思,若是有必要裝飾BeanDefinition對象
咱們進入代碼來看一下:
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) { return this.decorateBeanDefinitionIfRequired(ele, definitionHolder, (BeanDefinition)null); }
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; NamedNodeMap attributes = ele.getAttributes(); for(int i = 0; i < attributes.getLength(); ++i) { Node node = attributes.item(i); finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd); } NodeList children = ele.getChildNodes(); for(int i = 0; i < children.getLength(); ++i) { Node node = children.item(i); if (node.getNodeType() == 1) { finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition; } public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) { String namespaceUri = this.getNamespaceURI(node); if (!this.isDefaultNamespace(namespaceUri)) { NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler != null) { return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); } if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) { this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); } else if (this.logger.isDebugEnabled()) { this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); } } return originalDef; }
能夠看到主要動做是,對屬性及子元素進行處理,若是是默認元素,直接掠過,若是不是則根據命名空間,查找對應的處理handler進行解析處理,具體的解析過程暫時先放這裏,後續再說。這裏
只介紹下作了什麼事情。
繼續咱們的核心步驟,該到註冊步驟了,將咱們的beanDefinition註冊到註冊表中。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); String[] aliases = definitionHolder.getAliases(); if (aliases != null) { String[] var4 = aliases; int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) { String alias = var4[var6]; registry.registerAlias(beanName, alias); } } }
這裏有兩個部分,一個是根據beanName註冊,一個是根據alias註冊
咱們看第一個根據beanName註冊:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition)beanDefinition).validate(); } catch (BeanDefinitionValidationException var4) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var4); } } BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + " with a framework-generated bean definition ': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { this.beanDefinitionNames.add(beanName); // 記錄beanName this.manualSingletonNames.remove(beanName); this.frozenBeanDefinitionNames = null; } this.beanDefinitionMap.put(beanName, beanDefinition); if (oldBeanDefinition != null || this.containsSingleton(beanName)) { this.resetBeanDefinition(beanName); // 重置全部beanName對應的緩存 } }
這裏還有一個校驗,這裏的校驗主要校驗的是methodOverrides,主要校驗是否有這個類和這個類是否有相應的方法。
這裏的操做:
1:校驗,校驗methodOverrides屬性的正確性和有效性
2:查看是否已經有了該beanName,若是有而後查看是否配置可覆蓋,若是不是,直接拋出異常;若是設置能夠覆蓋,那麼在後續的操做中覆蓋掉便可
3:加入map緩存
4:清除解析前留下的beanName緩存
繼續:經過別名註冊BeanDefinition
public void registerAlias(String name, String alias) { Assert.hasText(name, "'name' must not be empty"); Assert.hasText(alias, "'alias' must not be empty"); if (alias.equals(name)) { this.aliasMap.remove(alias); } else { if (!this.allowAliasOverriding()) { String registeredName = (String)this.aliasMap.get(alias); if (registeredName != null && !registeredName.equals(name)) { throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } } this.checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); } }
步驟以下:
1:若是alias名字與name相同,直接刪除原有alias
2:查看是否容許alias覆蓋配置,若是不容許,進行校驗,若是已經註冊的alias的beanName跟當前註冊的beanName不相同,則拋出alias名稱已被註冊到其餘beanName上的異常
3:檢查是否有循環alias
4:註冊alias
至此,默認標籤的解析就梳理完了,後續咱們進行自定義標籤的解析。2019-07-01 17:32分 於圖書館