processBeanDefinition()
負責 Bean 標籤的解析,在解析過程中首先調用BeanDefinitionParserDelegate.parseBeanDefinitionElement()
完成默認標籤的解析,如果解析成功(返回的 bdHolder != null ),則首先調用 BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()
完成自定義標籤元素解析,前面四篇文章已經分析了默認標籤的解析,所以這篇文章分析自定義標籤的解析。
-
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
-
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
-
}
調用 decorateBeanDefinitionIfRequired()
:
-
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()
裝飾節點(子節點)。
-
public BeanDefinitionHolder decorateIfRequired(
-
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
-
// 獲取自定義標籤的命名空間
-
String namespaceUri = getNamespaceURI(node);
-
// 過濾掉默認命名標籤
-
if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
-
// 獲取相應的處理器
-
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
-
if (handler != null) {
-
// 進行裝飾處理
-
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 {
-
if (logger.isDebugEnabled()) {
-
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
-
}
-
}
-
}
-
return originalDef;
-
}
首先獲取自定義標籤的命名空間,如果不是默認的命名空間則根據該命名空間獲取相應的處理器,最後調用處理器的 decorate()
進行裝飾處理。具體的裝飾過程這裏不進行講述,在後面分析自定義標籤時會做詳細說明。
至此,Bean 的解析過程已經全部完成了,下面做一個簡要的總結。
解析 BeanDefinition 的入口在 DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()
。該方法會根據命令空間來判斷標籤是默認標籤還是自定義標籤,其中默認標籤由 parseDefaultElement()
實現,自定義標籤由 parseCustomElement()
實現。在默認標籤解析中,會根據標籤名稱的不同進行 import 、alias 、bean 、beans 四大標籤進行處理,其中 bean 標籤的解析爲核心,它由 processBeanDefinition()
方法實現。 processBeanDefinition()
開始進入解析核心工作,分爲三步:
-
解析默認標籤:
BeanDefinitionParserDelegate.parseBeanDefinitionElement()
-
解析默認標籤下的自定義標籤:
BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()
-
註冊解析的 BeanDefinition:
BeanDefinitionReaderUtils.registerBeanDefinition
在默認標籤解析過程中,核心工作由 parseBeanDefinitionElement()
方法實現,該方法會依次解析 Bean 標籤的屬性、各個子元素,解析完成後返回一個 GenericBeanDefinition 實例對象。
原文發佈時間爲:2018-09-26
本文作者:Java技術驛站
本文來自雲棲社區合作伙伴“Java技術驛站”,瞭解相關信息可以關注“Java技術驛站”。