Spring配置文件解析之BeanDefinitionDocumentReader詳解
Spring中的BeanDefinitionDocumentReader
上一篇Spring配置文件解析之BeanDefinitionReader詳解中我們已經(jīng)了解到BeanDefinitionReader已經(jīng)將Spring的xml配置文件解析成Document對象了,接下來的解析處理工作是在BeanDefinitionDocumentReader中對Document對象進行解析工作了。
BeanDefinitionDocumentReader接口及其實現(xiàn)類:

BeanDefinitionDocumentReader提供的方法:
public interface BeanDefinitionDocumentReader {
void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
throws BeanDefinitionStoreException;
}在 BeanDefinitionDocumentReader的實現(xiàn)類DefaultBeanDefinitionDocumentReader定義了對一些xml配置文件基本的元素的解析處理操作

在這里我們可能會有一個疑問,在Spring的xml配置文件中經(jīng)常看到的aop等相關(guān)的配置是在什么地方解析處理的,其實他們都是通過NamespaceHandler實現(xiàn)類來完成的,接下來我們會對其進行詳細(xì)的介紹。
在DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法中開始對Document進行解析。
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}在doRegisterBeanDefinitions中會創(chuàng)建BeanDefinitionParserDelegate來對Document進行解析
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
//創(chuàng)建BeanDefinitionParserDelegate,真正xml中各種元素的解析
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}在parseBeanDefinitions會對Node進行判斷,如果是上面配置默認(rèn)解析的spring標(biāo)簽,則會在DefaultBeanDefinitionDocumentReader中進行解析,否則的話就需要 BeanDefinitionParserDelegate來委派找到解析處理器。
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)) {
//默認(rèn)的一些標(biāo)簽在DefaultBeanDefinitionDocumentReader進行解析
parseDefaultElement(ele, delegate);
}
else {
//如果不是默認(rèn)的就需要在通過委派模式來尋找解析處理器
delegate.parseCustomElement(ele);
}
}
}
}
else {
//如果不是默認(rèn)的就需要在通過委派模式來尋找解析處理器
delegate.parseCustomElement(root);
}
}在parseDefaultElement中會對一些默認(rèn)的標(biāo)簽import,alias,bean,beans標(biāo)簽進行處理
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//解析import標(biāo)簽
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//解析alias標(biāo)簽
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//解析bean標(biāo)簽
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//解析beans標(biāo)簽,就是進行遞歸解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
對bean標(biāo)簽解析,最終還是在BeanDefinitionParserDelegate中對元素進行處理解析生成BeanDefinitionHolder,其實bean元素的解析的結(jié)果是一個BeanDefinition對象,其包含了所有的bean的屬性設(shè)置,processBeanDefinition中的BeanDefinitionReaderUtils的處理結(jié)果是將BeanDefinition注冊到BeanFactory中。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//最終還是在BeanDefinitionParserDelegate中進行元素解析
//BeanDefinitionHolder是對BeanDefinition的封裝,包括BeanDefinition,beanName,aliases
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//處理的操作是將bean的元數(shù)據(jù)BeanDifinition注冊到BeanFactory中
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));
}
}總結(jié)
BeanDefinitionDocumentReader中也沒有對xml中的bean元素進行處理操作,其真正的處理操作是在BeanDefinitionParserDelegate中進行處理的,都是在為他人做嫁衣。
到此這篇關(guān)于Spring配置文件解析之BeanDefinitionDocumentReader詳解的文章就介紹到這了,更多相關(guān)Spring中的BeanDefinitionDocumentReader內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Thymeleaf渲染網(wǎng)頁時中文亂碼的問題及解決
這篇文章主要介紹了Thymeleaf渲染網(wǎng)頁時中文亂碼的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
SpringAOP事務(wù)配置語法及實現(xiàn)過程詳解
這篇文章主要介紹了SpringAOP事務(wù)配置語法及實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Double.parseDouble()與Double.valueOf()的區(qū)別及說明
這篇文章主要介紹了Double.parseDouble()與Double.valueOf()的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
springboot2.0以上調(diào)度器配置線程池的實現(xiàn)
這篇文章主要介紹了springboot2.0以上調(diào)度器配置線程池的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
IDEA2022 提示更新 TKK失敗請檢查網(wǎng)絡(luò)連接的問題
這篇文章主要介紹了IDEA2022 提示:更新 TKK 失敗,請檢查網(wǎng)絡(luò)連接,本文給大家分享解決方案,對idea2022提示更新TKK失敗感興趣的朋友跟隨小編一起看看吧2022-11-11

